0

I am building a stock trading app, and trying to calculate a users total portfolio value over time to display it in a dashboard using react-chartjs-2:

Here's my nosql data:

// stocks array
const stocks = [
  {
    symbol: "AAPL",
    name: "Apple Inc.",
    prices: [138.4, 135.46, 140.12, 70.24, 70.17]
  },
  {
    symbol: "GOOG",
    name: "Alphabet Inc.",
    prices: [2648.76, 2695.99, 2682.71, 100.22, 100.88]
  }
];

// trades array
const trades = [
  {
    id: 1,
    user_id: "123",
    type: "buy",
    stock: "AAPL",
    quantity: 100,
    price: 138.4,
    date: "2023-02-16"
  },
  {
    id: 2,
    user_id: "123",
    type: "sell",
    stock: "AAPL",
    quantity: 50,
    price: 140.12,
    date: "2023-02-17"
  },
  {
    id: 3,
    user_id: "123",
    type: "buy",
    stock: "GOOG",
    quantity: 75,
    price: 2695.99,
    date: "2023-02-17"
  },
  {
    id: 4,
    user_id: "123",
    type: "buy",
    stock: "AAPL",
    quantity: 100,
    price: 142.24,
    date: "2023-02-18"
  },
  {
    id: 5,
    user_id: "123",
    type: "buy",
    stock: "GOOG",
    quantity: 100,
    price: 2704.22,
    date: "2023-02-18"
  },
  {
    id: 6,
    user_id: "123",
    type: "buy",
    stock: "AAPL",
    quantity: 100,
    price: 143.17,
    date: "2023-02-19"
  },
  {
    id: 7,
    user_id: "123",
    type: "buy",
    stock: "GOOG",
    quantity: 100,
    price: 2676.88,
    date: "2023-02-19"
  }
];

We then iterate over each trade object in the trades array, finding the stock associated with each trade in the stocks array and calculating the value of the trade based on the stock's price history. The resulting portfolio object contains keys that represent each date that the user made a trade, and the value of each key is an object that contains a date and a value:

  const portfolio = trades.reduce((acc, trade) => {
    const stock = stocks.find((s) => s.symbol === trade.stock);
    const value =
      stock.prices.find((price, index) => {
        if (
          index === stock.prices.length - 1 ||
          stock.prices[index + 1] > trade.price
        ) {
          return true;
        }
        return false;
      }) * trade.quantity;
    const date = trade.date;

    if (!acc[date]) {
      acc[date] = { date, value };
    } else {
      acc[date].value += value;
    }
    return acc;
  }, {});

  const portfolioData = Object.values(portfolio)
    .sort((a, b) => new Date(a.date) - new Date(b.date))
    .map((p) => ({ date: p.date, value: p.value.toFixed(2) }));

Which returns:

[{"date":"2023-02-16","value":"13546.00"},{"date":"2023-02-17","value":"11074.50"},{"date":"2023-02-18","value":"17105.00"},{"date":"2023-02-19","value":"271893.00"}]

My problem arises when I try to map the data to a line chart using react-chartjs-2:

const LineChart = ({ portfolioData }) => {
  const chartData = {
    labels: portfolioData.map((data) => data.date),
    datasets: [
      {
        label: "Portfolio Value",
        data: portfolioData.map((data) => data.value),
        fill: false,
        backgroundColor: "rgba(75,192,192,0.4)",
        borderColor: "rgba(75,192,192,1)"
      }
    ]
  };

  return <Line data={chartData} />;
};

And use in my component like:

<LineChart portfolioData={portfolioData} />

I get the error:

"category" is not a registered scale.

What am I doing wrong here? Full code and sandbox:

import "./styles.css";
import { Line } from "react-chartjs-2";

// stocks array
const stocks = [
  {
    symbol: "AAPL",
    name: "Apple Inc.",
    prices: [138.4, 135.46, 140.12, 70.24, 70.17]
  },
  {
    symbol: "GOOG",
    name: "Alphabet Inc.",
    prices: [2648.76, 2695.99, 2682.71, 100.22, 100.88]
  }
];

// trades array
const trades = [
  {
    id: 1,
    user_id: "123",
    type: "buy",
    stock: "AAPL",
    quantity: 100,
    price: 138.4,
    date: "2023-02-16"
  },
  {
    id: 2,
    user_id: "123",
    type: "sell",
    stock: "AAPL",
    quantity: 50,
    price: 140.12,
    date: "2023-02-17"
  },
  {
    id: 3,
    user_id: "123",
    type: "buy",
    stock: "GOOG",
    quantity: 75,
    price: 2695.99,
    date: "2023-02-17"
  },
  {
    id: 4,
    user_id: "123",
    type: "buy",
    stock: "AAPL",
    quantity: 100,
    price: 142.24,
    date: "2023-02-18"
  },
  {
    id: 5,
    user_id: "123",
    type: "buy",
    stock: "GOOG",
    quantity: 100,
    price: 2704.22,
    date: "2023-02-18"
  },
  {
    id: 6,
    user_id: "123",
    type: "buy",
    stock: "AAPL",
    quantity: 100,
    price: 143.17,
    date: "2023-02-19"
  },
  {
    id: 7,
    user_id: "123",
    type: "buy",
    stock: "GOOG",
    quantity: 100,
    price: 2676.88,
    date: "2023-02-19"
  }
];

const LineChart = ({ portfolioData }) => {
  const chartData = {
    labels: portfolioData.map((data) => data.date),
    datasets: [
      {
        label: "Portfolio Value",
        data: portfolioData.map((data) => data.value),
        fill: false,
        backgroundColor: "rgba(75,192,192,0.4)",
        borderColor: "rgba(75,192,192,1)"
      }
    ]
  };

  return <Line data={chartData} />;
};

const App = () => {
  const portfolio = trades.reduce((acc, trade) => {
    const stock = stocks.find((s) => s.symbol === trade.stock);
    const value =
      stock.prices.find((price, index) => {
        if (
          index === stock.prices.length - 1 ||
          stock.prices[index + 1] > trade.price
        ) {
          return true;
        }
        return false;
      }) * trade.quantity;
    const date = trade.date;

    if (!acc[date]) {
      acc[date] = { date, value };
    } else {
      acc[date].value += value;
    }
    return acc;
  }, {});

  const portfolioData = Object.values(portfolio)
    .sort((a, b) => new Date(a.date) - new Date(b.date))
    .map((p) => ({ date: p.date, value: p.value.toFixed(2) }));
  console.log(portfolioData);
  return (
    <div>
      {JSON.stringify(portfolioData)}
      <LineChart portfolioData={portfolioData} />
    </div>
  );
};

export default App;
a7dc
  • 3,323
  • 7
  • 32
  • 50

0 Answers0