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

View File

@ -16,35 +16,46 @@
return `Q${quarter} '${year}`;
};
const price = data?.getStockQuote?.price?.toFixed(2) || 0;
const calculatePriceChange = (targetPrice) =>
targetPrice && price ? ((targetPrice / price - 1) * 100)?.toFixed(2) : 0;
const avgPriceTarget = data?.getPriceAnalysis?.avgPriceTarget || 0;
const medianPriceTarget = data?.getPriceAnalysis?.medianPriceTarget || 0;
const lowPriceTarget = data?.getPriceAnalysis?.lowPriceTarget || 0;
const highPriceTarget = data?.getPriceAnalysis?.highPriceTarget || 0;
function prepareDataset() {
price = data?.getStockQuote?.price?.toFixed(2) || 0;
const lowChange = calculatePriceChange(lowPriceTarget);
const medianChange = calculatePriceChange(medianPriceTarget);
const avgChange = calculatePriceChange(avgPriceTarget);
const highChange = calculatePriceChange(highPriceTarget);
avgPriceTarget = data?.getPriceAnalysis?.avgPriceTarget || 0;
medianPriceTarget = data?.getPriceAnalysis?.medianPriceTarget || 0;
lowPriceTarget = data?.getPriceAnalysis?.lowPriceTarget || 0;
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")
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.
if (historicalData && historicalData.length) {
const latest = historicalData.at(-1);
backtestList.push({ date: latest.time });
if (historicalData && historicalData?.length) {
const latest = historicalData?.at(-1);
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.
// Then, if a score exists, attach a marker and data label based on the score.
const processedData = backtestList?.map((item) => {
processedData = backtestList?.map((item) => {
const dateStr = item.date;
const targetTime = new Date(dateStr).getTime();
let closestPoint = historicalData[0];
@ -102,18 +113,18 @@
return dataPoint;
});
const tableDates = processedData
tableDates = processedData
?.slice(0, -1)
?.map((item) => formatDateToQuarter(item.x));
?.map((item) => formatDateToQuarter(item?.x));
const tableScore = processedData
tableScore = processedData
?.slice(0, -1)
?.map((item) => item?.dataLabels?.format);
// Compute percentage change
const tableQuarterChange = processedData
tableQuarterChange = processedData
?.slice(0, -1)
.map((item, index, arr) => {
?.map((item, index, arr) => {
const prevY = arr[index - 1]?.y; // Get the previous value
if (prevY == null || item.y == null) return null; // Handle missing values
const change = ((item.y - prevY) / prevY) * 100; // Calculate percentage change
@ -125,7 +136,7 @@
?.filter(Boolean); // Remove null values
// Compute Average Return
const returns = processedData
returns = processedData
?.slice(1) // Skip the first value since there's no previous value for it
?.map((item, index) => {
const prevY = processedData[index]?.y;
@ -135,9 +146,42 @@
})
.filter(Boolean); // Remove null values
const avgReturn =
avgReturn =
returns?.reduce((sum, returnPercentage) => sum + returnPercentage, 0) /
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() {
const solidData = processedData.slice(0, -1);
@ -422,7 +466,8 @@
let configScore = null;
$: {
if ($mode) {
if ($stockTicker || $mode) {
prepareDataset();
configScore = getAIScorePlot() || null;
config = getPriceForecastChart() || null;
}