1

I'm trying to display financial data on a web app using the Chart.js library.

In my Node.js app, a user uploads a csv file. This file gets processed into a pandas dataframe by a flask rest api. The dataframe is saved on the flask server and is accessible via a get request. The get request returns a JSON object with fields Open, High, Low, Close, and Volume. These fields hold arrays.

I have a web socket (socket.io) established between my express server and a react component. My express server pings my flask api looking for the chart data. When the chart data is available (after uploading a file) the socket sends this data to the component. The client socket triggers a component method that creates the chart. A chart appears but has no data points displayed.

The component:

class Canvas extends Component {
    constructor(props){
        super(props);
        this.state = {
            data: false,
            endpoint: 'http://localhost:4000'
        }

        this.establishSocket = this.establishSocket.bind(this);
        this.makeChart = this.makeChart.bind(this);
    }

    componentDidMount() {
        this.establishSocket();
    }

    establishSocket() {
        const { endpoint } = this.state;
        const socket = socketIOClient(endpoint);
        socket.on("ohlcv_data", data => this.makeChart(data.Close));
    }

    makeChart(datapoints) {
        this.setState({ data: datapoints })
        var ctx = document.getElementById("myChart");
        var myChart = new Chart(ctx, {
            type: 'line',
            data: datapoints,
            options: { 
                responsive: true, 
                maintainAspectRatio: false
            }
        });
        console.log(myChart.data);
    }

    render() {
        return (
            <div id="chartContainer">
                <canvas id="myChart"></canvas>
            </div>
        )
    }
}

The charting code has been adapted from the Chart.js docs here:

https://www.chartjs.org/docs/latest/getting-started/usage.html

https://www.chartjs.org/docs/latest/charts/line.html

This is my app with the empty chart: enter image description here

The console log at the bottom of the makeChart function displays the expected array. This is the output of that log:

enter image description here

My question is, what am I missing in this implementation in order to get the data to appear?

1
  • Just a random comment: you might want to consider using a react implementation of chart.js such as npmjs.com/package/react-chartjs-2 Commented Sep 12, 2018 at 0:09

2 Answers 2

3

I could be wrong, but it looks like the input data for your linechart is in an incorrect format. Looking here at chartJs' documentation, you either have to specify the x and y of each point individually using an array of objects, or in your case, when passing an array of numbers, specify a labels array.

When the data array is an array of numbers, the x axis is generally a category. The points are placed onto the axis using their position in the array. When a line chart is created with a category axis, the labels property of the data object must be specified.

You can see how to do that here, so your chart data param should look like this:

let chart = new Chart(ctx, {
    type: ...
    data: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June'],
        datasets: ...
    },
});

Sign up to request clarification or add additional context in comments.

1 Comment

I think you may be right. I read more carefully this time at the example here and it says: The data property of a dataset for a line chart can be passed in two formats. I am setting the data property of the object itself based on the example of using an array for the data property of a dataset.
1

Thanks to cdm for putting me in the right direction. I remembered that one of my github repositories has chart.js implementations that my teammates made which replaced the google charts that I was using originally.

They are implemented like so:

makeChart(datapoints) {
    this.setState({ data: datapoints })
    var ctx = document.getElementById("myChart");
    var datapoints = datapoints.slice(0,100)
    var config = {
        type: 'line',
        data: {
            labels: this.linspace(0,datapoints[0],datapoints.length),
            datasets: [{
                data: datapoints,
                label: "Price:",
                borderColor: "#3e95cd",
                fill: false
            }]
        },
        options: {
            title: {
                display: true,
                text: 'WTI Closing Price'
            },
            legend: {
                display: false
            }
        }
    }
    var myChart = new Chart(ctx, config );
}

This configuration format works as expected producing the chart below: enter image description here

For completeness, for those who may use this exact code, the linspace function is implemented as follows:

precisionRound(number, precision) {
    var factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
}

linspace (a, b, n) {
    if (typeof n === 'undefined') n = Math.max(Math.round(b - a) + 1, 1)
    if (n < 2) {
        return n === 1 ? [a] : []
    }
    var i,ret = Array(n)
    n--
    for (i = n;i >= 0;i--) {
        ret[i] = this.precisionRound((i * b + (n - i) * a) / n, 2)
    }
    return ret
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.