Plotting stock prices in Three.js (3D scatter plot)

      A few days ago I came across a node module called yahoo-finance. The module allows users to parse the csv file from yahoo server and return it in a nice json format. So I thought it would be interesting to fetch the stock prices of S&P 500 of the year 2013 and find a way to plot it. And the result looks amazing. (repo here)

The code does a few things:

on the server side
  • fetch the stock info and save it as a json file
on the client side]
  • request the json file with AngularJS
  • render the data with Three.js

The server side script does a general job of formatting, and the final json file is of the following format:

{ 
    "symbols" : {
        "AAPL": [
          549.03,
          542.1
          ]
    },
    "date" : [
        "2013-01-01T16:00:00.000Z",
        "2013-01-02T16:00:00.000Z"
           ]
}

which I simply save inside a public folder for AugularJS to request. (the final json file)

The majority of the time was spent on writing the code for AngularJS, and it was a great practice since it was my first time writing a derivative.

I based my code on the project here. The author, Casey Lang, shows a complete example of plotting randomized points inside a 3D square box. And he provides an extra functionality to animate the points dropping to the floor, which I thought was pretty cool.

But it is much flexible when applying Three.js inside an Angular derivative. Specifically, scope.$watch is useful for triggering the rendering after the json file is done loading.

scope.$watch('stockData', function (newValue) {
   if(newValue.content){ 
      stockData = newValue.content; 
      init();
      animate();
    }
 }, true);

The init() function initializes the Three.js 3D object, parses the stockData, and add mouse events to the div. And animate() uses itself as the callback function as following:

  function animate() {
    requestAnimationFrame( animate, renderer.domElement);
    render();
  }

One of the most useful object in Three.js is perhaps Clock.
For example, I added the few lines inside render() to stop the rendering if the mouse has been idle for more than 1 second.

update = clock.getElapsedTime() - elapsedTime > 1 ? false : true;
    if(update){
        // start rendering
    }

The clock and elapsedTime are both global variables. clock starts counting when initiated, and elapsedTime remembers the time when the mouse events are last triggered. So the update boolean value makes sure the rendering occurs within 1 second of last mouse movement.

Three.js Official Page

Simple integration of AngularJS and ThreeJS

comments powered by Disqus