update forecast ai page

This commit is contained in:
MuslemRahimi 2025-03-13 10:41:07 +01:00
parent 57fa0224bf
commit fa70a10672
2 changed files with 158 additions and 113 deletions

View File

@ -41,10 +41,10 @@
AI Score Definition AI Score Definition
</h3> </h3>
<div class=" p-2"> <div class=" p-2">
Revenue, also called sales, is the amount of money a company The AI Score uses fundamental and technical indicators, along
receives from its business activities, such as sales of products with statistical data, to predict if a stock will be bullish in
or services. Revenue does not take any expenses into account and the next quarter. It ranges from 1 to 10, with higher scores
is therefore different from profits. indicating a greater likelihood of the prediction being correct.
</div> </div>
<!-- <!--
<div class="px-2"> <div class="px-2">
@ -67,10 +67,10 @@
AI Trend Forecast Definition AI Trend Forecast Definition
</h3> </h3>
<div class=" p-2"> <div class=" p-2">
Revenue, also called sales, is the amount of money a company The AI Trend Model forecasts stock trends by analyzing
receives from its business activities, such as sales of products historical price data. It detects patterns, seasonality, and
or services. Revenue does not take any expenses into account and trends to predict future price movements, making it useful for
is therefore different from profits. predicting price targets for the next 12 months.
</div> </div>
<!-- <!--
<div class="px-2"> <div class="px-2">

View File

@ -16,35 +16,46 @@
return `Q${quarter} '${year}`; return `Q${quarter} '${year}`;
}; };
const price = data?.getStockQuote?.price?.toFixed(2) || 0;
const calculatePriceChange = (targetPrice) => const calculatePriceChange = (targetPrice) =>
targetPrice && price ? ((targetPrice / price - 1) * 100)?.toFixed(2) : 0; targetPrice && price ? ((targetPrice / price - 1) * 100)?.toFixed(2) : 0;
const avgPriceTarget = data?.getPriceAnalysis?.avgPriceTarget || 0; function prepareDataset() {
const medianPriceTarget = data?.getPriceAnalysis?.medianPriceTarget || 0; price = data?.getStockQuote?.price?.toFixed(2) || 0;
const lowPriceTarget = data?.getPriceAnalysis?.lowPriceTarget || 0;
const highPriceTarget = data?.getPriceAnalysis?.highPriceTarget || 0;
const lowChange = calculatePriceChange(lowPriceTarget); avgPriceTarget = data?.getPriceAnalysis?.avgPriceTarget || 0;
const medianChange = calculatePriceChange(medianPriceTarget); medianPriceTarget = data?.getPriceAnalysis?.medianPriceTarget || 0;
const avgChange = calculatePriceChange(avgPriceTarget); lowPriceTarget = data?.getPriceAnalysis?.lowPriceTarget || 0;
const highChange = calculatePriceChange(highPriceTarget); highPriceTarget = data?.getPriceAnalysis?.highPriceTarget || 0;
lowChange = calculatePriceChange(lowPriceTarget);
medianChange = calculatePriceChange(medianPriceTarget);
avgChange = calculatePriceChange(avgPriceTarget);
highChange = calculatePriceChange(highPriceTarget);
// Assume data.getHistoricalPrice contains objects with a "time" field (e.g. "2015-01-02") // Assume data.getHistoricalPrice contains objects with a "time" field (e.g. "2015-01-02")
const historicalData = data?.getHistoricalPrice || []; historicalData = data?.getHistoricalPrice || [];
const backtestList = data?.getAIScore?.backtest || []; backtestList = data?.getAIScore?.backtest || [];
// Append the latest historical date (using "time") if available. Note that this entry may not include a score. // Append the latest historical date (using "time") if available. Note that this entry may not include a score.
if (historicalData && historicalData.length) { if (historicalData && historicalData?.length) {
const latest = historicalData.at(-1); const latest = historicalData?.at(-1);
backtestList.push({ date: latest.time }); backtestList?.push({ date: latest.time });
const seenDates = new Set();
backtestList = backtestList?.filter((item) => {
// Check if the date is already seen
if (seenDates?.has(item?.date)) {
// If yes, skip this duplicate (delete the last one)
return false;
}
// Otherwise, record the date and keep the item
seenDates?.add(item?.date);
return true;
});
} }
// For each backtest entry, find the historical price with the closest available time. processedData = backtestList?.map((item) => {
// Then, if a score exists, attach a marker and data label based on the score.
const processedData = backtestList?.map((item) => {
const dateStr = item.date; const dateStr = item.date;
const targetTime = new Date(dateStr).getTime(); const targetTime = new Date(dateStr).getTime();
let closestPoint = historicalData[0]; let closestPoint = historicalData[0];
@ -102,18 +113,18 @@
return dataPoint; return dataPoint;
}); });
const tableDates = processedData tableDates = processedData
?.slice(0, -1) ?.slice(0, -1)
?.map((item) => formatDateToQuarter(item.x)); ?.map((item) => formatDateToQuarter(item?.x));
const tableScore = processedData tableScore = processedData
?.slice(0, -1) ?.slice(0, -1)
?.map((item) => item?.dataLabels?.format); ?.map((item) => item?.dataLabels?.format);
// Compute percentage change // Compute percentage change
const tableQuarterChange = processedData tableQuarterChange = processedData
?.slice(0, -1) ?.slice(0, -1)
.map((item, index, arr) => { ?.map((item, index, arr) => {
const prevY = arr[index - 1]?.y; // Get the previous value const prevY = arr[index - 1]?.y; // Get the previous value
if (prevY == null || item.y == null) return null; // Handle missing values if (prevY == null || item.y == null) return null; // Handle missing values
const change = ((item.y - prevY) / prevY) * 100; // Calculate percentage change const change = ((item.y - prevY) / prevY) * 100; // Calculate percentage change
@ -125,7 +136,7 @@
?.filter(Boolean); // Remove null values ?.filter(Boolean); // Remove null values
// Compute Average Return // Compute Average Return
const returns = processedData returns = processedData
?.slice(1) // Skip the first value since there's no previous value for it ?.slice(1) // Skip the first value since there's no previous value for it
?.map((item, index) => { ?.map((item, index) => {
const prevY = processedData[index]?.y; const prevY = processedData[index]?.y;
@ -135,9 +146,42 @@
}) })
.filter(Boolean); // Remove null values .filter(Boolean); // Remove null values
const avgReturn = avgReturn =
returns?.reduce((sum, returnPercentage) => sum + returnPercentage, 0) / returns?.reduce((sum, returnPercentage) => sum + returnPercentage, 0) /
returns?.length; returns?.length;
}
let price;
let avgPriceTarget;
let medianPriceTarget;
let lowPriceTarget;
let highPriceTarget;
let lowChange;
let medianChange;
let avgChange;
let highChange;
let historicalData;
let backtestList;
// For each backtest entry, find the historical price with the closest available time.
// Then, if a score exists, attach a marker and data label based on the score.
let processedData = [];
let tableDates;
let tableScore;
// Compute percentage change
let tableQuarterChange;
// Compute Average Return
let returns;
let avgReturn;
function getAIScorePlot() { function getAIScorePlot() {
const solidData = processedData.slice(0, -1); const solidData = processedData.slice(0, -1);
@ -422,7 +466,8 @@
let configScore = null; let configScore = null;
$: { $: {
if ($mode) { if ($stockTicker || $mode) {
prepareDataset();
configScore = getAIScorePlot() || null; configScore = getAIScorePlot() || null;
config = getPriceForecastChart() || null; config = getPriceForecastChart() || null;
} }