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}`));

1 Like

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.

1 Like

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:

1 Like

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

1 Like

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 },
      });
2 Likes