// Made by Abhishek Malaviya
// Leave this trail here if you clone it
// Update v1.0:
// 1) Stock Data Fetching (Retrieves real-time stock prices, market cap, volume, etc. from Yahoo Finance API)
// 2) Analyst Recommendations (Displays stock recommendations based on analyst ratings)
// 3) Handles errors gracefully with clear messages (Error handling when data fetching fails)
// 4) Added real-time stock symbol input and fetching mechanism
// Update v1.1:
// 1) Improved Error Handling (Enhanced error prevention for missing data and failed requests)
// 2) Improved UI Layout (Background Colour, Aligned display of stock data and news for better user experience)
// 3) Refined Stock Symbol Input (Now accepts user input for any stock symbol, automatically converts to uppercase)
// 4) Console Logs for Debugging (Added logs to help track responses from APIs and data flow)
// Future v2.0 Plans:
// 1) Latest News Fetching (Fetches latest news related to the stock using the Investing News API)
// 2) Add Interactive Charts (To visually represent stock trends over time)
// 3) Improve Recommendation Logic (Use more complex analysis to provide buy/sell recommendations)
// 4) Extend News Fetching to Multiple Sources (Integrate more news APIs for diverse updates)
// 5) Redesign UI for better user experience and visualization of stock trends
// 6) Optimize API Fetching Logic for faster response times and better data accuracy
// Disclaimer: I have used Inspect Element’s AI tools and other debugging methods for understanding and improving the code,
// but the entire code is not made by AI. All code has been manually implemented and adjusted for the project’s needs.
// API KEY CONFIGURATION
const apiKey = "8e4cfa683cmshe2485f38a519a4bp1dd3afjsna53e1e493c72"; // Yahoo Finance API Key
const newsApiUrl = "https://investing11.p.rapidapi.com/get_news?news_type=latest&page=1"; // News API URL
// Bg styling config
document.write(`
<style>
body {
margin: 0;
padding: 0;
height: 100vh;
background: linear-gradient(45deg, blue, purple);
background-size: 200% 200%;
animation: gradientAnimation 15s ease infinite;
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
z-index: -1;
position: relative;
}
@keyframes gradientAnimation {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.content {
text-align: center;
color: white;
z-index: 1;
position: relative;
}
button {
margin-top: 10px;
padding: 10px;
cursor: pointer;
background-color: #3498db;
color: #fff;
border-radius: 5px;
border: none;
font-size: 1rem;
}
#stockDataDisplay {
background: inherit;
padding: 20px;
border-radius: 10px;
font-size: 1.5rem;
color: white;
margin-top: 20px;
font-weight: bold;
}
input {
width: 50vw;
padding: 10px;
font-size: 1rem;
margin-top: 10px;
border-radius: 5px;
border: none;
background-color: rgba(255, 255, 255, 0.8);
}
#errorDisplay {
color: red;
font-size: 1.2rem;
font-weight: bold;
margin-top: 20px;
}
</style>
`);
// HTML Structure
document.write(`
<div class="content">
<h1>Stock Recommendation System</h1>
<h3>Enter a stock ticker symbol to get the latest stock price and news sentiment.</h3>
<div id="generated-quiz">
<p id="generationText">Generation takes around 5 seconds...</p>
<input id="stockTicker" placeholder="Enter Ticker" value="MSFT">
<button onclick="fetchStockData();">Get Stock Data & News</button>
<div id="stockDataDisplay"></div>
<div id="errorDisplay"></div>
</div>
</div>
`);
// Function to Fetch Stock Data
async function fetchStockData() {
const stockSymbol = document.getElementById("stockTicker").value.toUpperCase();
const stockUrl = `https://yahoo-finance15.p.rapidapi.com/api/v1/markets/stock/quotes?ticker=${stockSymbol}®ion=US`;
try {
const response = await fetch(stockUrl, {
method: 'GET',
headers: {
'x-rapidapi-key': apiKey,
'x-rapidapi-host': 'yahoo-finance15.p.rapidapi.com',
},
});
const data = await response.json();
console.log("Stock Data:", data);
// MH edit
console.log ( "Yahoo response:");
console.log ( data.body[0] );
if (data && data.body && data.body.length > 0) {
const stockData = data.body[0];
const output = `
Stock Symbol: ${stockData.symbol}<br>
Price: $${stockData.regularMarketPrice}<br>
Market Cap: ${stockData.marketCap}<br>
Volume: ${stockData.regularMarketVolume}<br>
Recommendation: ${getRecommendation(stockData.averageAnalystRating)}
`;
document.getElementById("stockDataDisplay").innerHTML = output;
} else {
handleError("Unable to fetch stock data. Please try again later.");
}
} catch (error) {
console.log("Fetch Stock Data Error:", error);
handleError("Error fetching stock data: " + error.message);
}
}
// Get Recommendation Based on Analyst Rating
function getRecommendation(analystRating) {
if (!analystRating) return "Neutral.";
if (analystRating.includes("Strong Buy")) return "Buy!";
if (analystRating.includes("Buy")) return "Consider Buying.";
if (analystRating.includes("Sell")) return "Sell.";
return "Neutral.";
}
// Function to Fetch News Data
function fetchNewsData(stockSymbol) {
// MH edit
console.log ("calling fetchNewsData");
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
try {
const response = JSON.parse(xhr.responseText);
console.log("News Response:", response);
if (response && response.data && Array.isArray(response.data)) {
const newsArticles = response.data.map(
(news) => news.headline || "No headline available"
);
displayNews(newsArticles);
} else {
document.getElementById("stockDataDisplay").innerHTML +=
"<br>No relevant news found.";
}
} catch (error) {
console.log("Fetch News Data Error:", error);
handleError("Error processing news response: " + error.message);
}
}
};
xhr.open("GET", newsApiUrl);
xhr.setRequestHeader("x-rapidapi-key", apiKey);
xhr.setRequestHeader("x-rapidapi-host", "investing11.p.rapidapi.com");
xhr.send();
}
// Display News Articles
function displayNews(newsArticles) {
const newsContent = `
<br>Latest News:<br>
${newsArticles.map((article, index) => `${index + 1}. ${article}<br>`).join("")}
`;
document.getElementById("stockDataDisplay").innerHTML += newsContent;
}
// Handle Errors
function handleError(message) {
document.getElementById("errorDisplay").textContent = message;
}