Intro to AI, Stock Ticker

I have completed intro to AI and downloaded the stock ticker zip and added to code to Visual Studio Code.

But when I try to add a ticker, such as MSFT or TSLA, nothing happens.

Here is the code:

<!doctype html>
<html>

	<head>
		<title>Dodgy Dave's Stock Predictions</title>
		<link rel="stylesheet" href="index.css">
		<link rel="preconnect" href="https://fonts.googleapis.com">
		<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
		<link href="https://fonts.googleapis.com/css2?family=Comic+Neue:wght@700&family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
		<meta name="viewport" content="width=device-width, initial-scale=1">
	</head>

	<body>
		<header>
			<img src="images/logo-dave-text.png" alt="Dodgy Dave's Stock Predictions">
		</header>
		<main>
			<section class="action-panel">
				<form id="ticker-input-form">
					<label for="ticker-input"> Add up to 3 stock tickers below to get a super accurate stock predictions reportšŸ‘‡ </label>
					<div class="form-input-control">
						<input type="text" id="ticker-input" placeholder="MSFT">
						<button class="add-ticker-btn">
							<img src="images/add.svg" class="add-ticker-svg" alt="add">
						</button>
					</div>
				</form>
				<p class="ticker-choice-display">
					Your tickers will appear here...
				</p>
				<button class="generate-report-btn" type="button" disabled>
					Generate Report
				</button>
				<p class="tag-line">Always correct 15% of the time!</p>
			</section>
			<section class="loading-panel">
				<img src="images/loader.svg" alt="loading">
				<div id="api-message">Querying Stocks API...</div>
			</section>
			<section class="output-panel">
				<h2>Your Report 😜</h2>
			</section>
		</main>
		<footer>
			&copy; This is not real financial advice!
		</footer>
		<script src="index.js" type="module"></script>
	</body>

</html>

const express = require('express');
const axios = require('axios');
const cors = require('cors');
require('dotenv').config();

const tickersArr = [];

const polygonApiKey = process.env.POLYGON_API_KEY;
const openaiApiKey = process.env.OPENAI_API_KEY;

console.log('Polygon API Key Loaded:', Boolean(polygonApiKey));
console.log('OpenAI API Key Loaded:', Boolean(openaiApiKey));

const app = express();
const PORT = process.env.PORT || 5000;

app.use(cors());
app.use(express.json());

// Middleware to check API keys
app.use((req, res, next) => {
    if (!polygonApiKey || !openaiApiKey) {
        return res.status(500).json({ error: 'API keys are not configured properly.' });
    }
    next();
});

document.querySelector('.add-ticker-btn').addEventListener('click', (e) => {
  e.preventDefault(); // Prevent the form from reloading the page
  const tickerInput = document.getElementById('ticker-input');
  const generateReportBtn = document.querySelector('.generate-report-btn');

  if (tickerInput.value.length > 2) {
      generateReportBtn.disabled = false;
      const newTickerStr = tickerInput.value.trim().toUpperCase();
      tickersArr.push(newTickerStr);
      tickerInput.value = ''; // Clear input field
      renderTickers();
  } else {
      const label = document.querySelector('label');
      label.style.color = 'red';
      label.textContent = 'You must add at least one valid ticker (3+ characters).';
  }
});

// Fetch stock data from Polygon.io
app.post('/api/stock-data', async (req, res) => {
    const { ticker, startDate, endDate } = req.body;

    try {
        const url = `https://api.polygon.io/v2/aggs/ticker/${ticker}/range/1/day/${startDate}/${endDate}?apiKey=${polygonApiKey}`;
        const response = await axios.get(url);
        res.status(200).json(response.data);
    } catch (error) {
        console.error('Error fetching stock data:', error.message);
        res.status(500).json({ error: 'Failed to fetch stock data.' });
    }
});

// Fetch AI report using OpenAI API
app.post('/api/generate-report', async (req, res) => {
    const { data } = req.body;

    try {
        const response = await axios.post(
            'https://api.openai.com/v1/chat/completions',
            {
                model: 'gpt-4',
                messages: [
                    {
                        role: 'system',
                        content: 'You are a trading guru. Write a short report based on the provided data.',
                    },
                    {
                        role: 'user',
                        content: data,
                    },
                ],
            },
            {
                headers: {
                    'Authorization': `Bearer ${openaiApiKey}`,
                    'Content-Type': 'application/json',
                },
            }
        );
        res.status(200).json(response.data.choices[0].message.content);
    } catch (error) {
        console.error('Error generating report:', error.message);
        res.status(500).json({ error: 'Failed to generate report.' });
    }
});

app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`));

Hey @Mark_Hording, sorry for the wait team just got back in after the holidays.

Do you receive any errors in your console when trying to fetch data from a ticker?

Also do you have a renderTickers( ) function? Could only spot you calling that function but couldn’t find it declared anywhere.

I have fixed adding a ticker, mostly now have issues with generating the report, so currently working on that.

Ah right. Any issues with the report generation let us know.

The main issue is with the Polygon API. The non-payment plan requires a two-week delay from Polygon and it is necessary to set a timeframe (which I have), but I keep getting the same error:

Error fetching stock data: Request failed with status code 400
Error details: {
** status: ā€˜ERROR’,**
** request_id: ā€˜bbdc2c2678e8913c49b96d02e6ef9975’,**
** error: ā€œCould not parse the time parameter: ā€˜from’. Use YYYY-MM-DD or Unix MS Timestampsā€**
}

Here is my index.js

const tickersArr = [];

document.querySelector('.add-ticker-btn').addEventListener('click', (e) => {
    e.preventDefault();
    const tickerInput = document.getElementById('ticker-input');
    const generateReportBtn = document.querySelector('.generate-report-btn');

    if (tickerInput.value.length > 2) {
        generateReportBtn.disabled = false;
        const newTickerStr = tickerInput.value.trim().toUpperCase();
        tickersArr.push(newTickerStr);
        tickerInput.value = '';
        renderTickers();
    } else {
        const label = document.querySelector('label');
        label.style.color = 'red';
        label.textContent = 'You must add at least one valid ticker (3+ characters).';
    }
});

function renderTickers() {
    const tickerDisplay = document.querySelector('.ticker-choice-display');
    tickerDisplay.innerHTML = tickersArr.join(', ');
}

async function generateStockReport() {
    if (tickersArr.length === 0) {
        alert("Please add at least one ticker.");
        return;
    }

    const ticker = tickersArr[0];
    const startDate = '2023-01-01';
    const endDate = '2023-01-31';

    try {
      const stockDataResponse = await axios.get('http://localhost:5001/api/stock-data', {
        params: {
            ticker: ticker,
            from: startDate,
            to: endDate,
        },
    });

        if (stockDataResponse.status !== 200 || !stockDataResponse.data) {
            throw new Error("Invalid stock data response.");
        }

        const stockData = stockDataResponse.data;

        const reportResponse = await axios.post('http://localhost:5001/api/generate-report', {
            data: JSON.stringify(stockData),
        });

        if (reportResponse.status !== 200 || !reportResponse.data) {
            throw new Error("Invalid report response.");
        }

        const report = reportResponse.data;
        document.querySelector('.output-panel').innerHTML = `<h2>Your Report 😜</h2><p>${report}</p>`;
    } catch (error) {
        console.error("Error during report generation:", error.message);
        console.error("Error details:", error.response ? error.response.data : error);
        alert(`An error occurred: ${error.message}`);
    }
}

document.querySelector('.generate-report-btn').addEventListener('click', generateStockReport);

I keep trying to re-write the code to comply with the requirements and/or have ChatGPT do it for me, but nothing works. So, I’m stuck :grin:

Getting more eyes on this for you @Mark_Hording. I’ll get a teacher in since they know more than me on this one! @Tom_Chant

Hi!
Is it possible that the format of your URL is not what the API expects?

const stockDataResponse = await axios.get('http://localhost:5001/api/stock-data', {
  params: {
      ticker: ticker,
      from: startDate,
      to: endDate,
  },

Would create something like:
...ticker=META&from=2023-01-09&to=2023-02-10

and not this:
...ticker/META/range/1/day/2023-01-09/2023-02-10

It would seem so, with some help from ChatGPT, I tried with the following and it worked:

    const stockDataResponse = await axios.get('http://localhost:5001/api/stock-data', {
          params: { ticker, startDate, endDate },
      });