From c6bf1b8d4f33678fbb506326733d708762d3a19b Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Fri, 1 Nov 2024 00:45:56 +0100 Subject: [PATCH] fix table --- src/lib/components/AnalystEstimate.svelte | 578 ++++++++++-------- .../stocks/[tickerID]/forecast/+page.svelte | 5 +- 2 files changed, 321 insertions(+), 262 deletions(-) diff --git a/src/lib/components/AnalystEstimate.svelte b/src/lib/components/AnalystEstimate.svelte index f40c7894..8ddadceb 100644 --- a/src/lib/components/AnalystEstimate.svelte +++ b/src/lib/components/AnalystEstimate.svelte @@ -15,10 +15,17 @@ let analystEstimateList = []; let isLoaded = false; - let deactivateContent = data?.user?.tier === "Pro" ? false : true; - let xData = []; - let optionsData; + let optionsRevenue = null; + let optionsEPS = null; + let revenueDateList = []; + let avgRevenueList = []; + let lowRevenueList = []; + let highRevenueList = []; + let epsDateList = []; + let avgEPSList = []; + let lowEPSList = []; + let highEPSList = []; let displayData = "Revenue"; @@ -39,14 +46,13 @@ return index !== -1 && hasNonNullRevenue ? index + 1 : index; } - function changeStatement(event) { - displayData = event.target.value; - } + let tableActualRevenue = []; + let tableActualEPS = []; - let tableDataActual = []; - let tableDataForecast = []; + let tableForecastRevenue = []; + let tableForecastEPS = []; - function getPlotOptions() { + function getPlotOptions(dataType: string) { let dates = []; let valueList = []; let avgList = []; @@ -62,27 +68,13 @@ const date = item.date?.toString().slice(-2); const isAfterStartIndex = stopIndex <= index + 1; dates.push(`FY${date}`); - switch (displayData) { + switch (dataType) { case "Revenue": valueList.push(item.revenue); avgList.push(isAfterStartIndex ? item.estimatedRevenueAvg : null); lowList.push(isAfterStartIndex ? item.estimatedRevenueLow : null); highList.push(isAfterStartIndex ? item.estimatedRevenueHigh : null); break; - case "Net Income": - valueList.push(item.netIncome); - avgList.push(isAfterStartIndex ? item.estimatedNetIncomeAvg : null); - lowList.push(isAfterStartIndex ? item.estimatedNetIncomeLow : null); - highList.push( - isAfterStartIndex ? item.estimatedNetIncomeHigh : null, - ); - break; - case "EBITDA": - valueList.push(item.ebitda); - avgList.push(isAfterStartIndex ? item.estimatedEbitdaAvg : null); - lowList.push(isAfterStartIndex ? item.estimatedEbitdaLow : null); - highList.push(isAfterStartIndex ? item.estimatedEbitdaHigh : null); - break; case "EPS": valueList.push(item.eps); avgList.push(isAfterStartIndex ? item.estimatedEpsAvg : null); @@ -189,87 +181,84 @@ ], }; - return option; + let currentYearSuffix = new Date().getFullYear().toString().slice(-2); + let searchString = `FY${currentYearSuffix}`; + + // Assign to global variables based on dataType + if (dataType === "Revenue") { + let currentYearIndex = dates?.findIndex((date) => date === searchString); + optionsRevenue = option; + revenueDateList = dates?.slice(currentYearIndex) || []; + avgRevenueList = avgList?.slice(currentYearIndex) || []; + lowRevenueList = lowList?.slice(currentYearIndex) || []; + highRevenueList = highList?.slice(currentYearIndex) || []; + } else if (dataType === "EPS") { + let currentYearIndex = dates?.findIndex((date) => date === searchString); + + optionsEPS = option; + epsDateList = dates?.slice(currentYearIndex) || []; + avgEPSList = avgList?.slice(currentYearIndex) || []; + lowEPSList = lowList?.slice(currentYearIndex) || []; + highEPSList = highList?.slice(currentYearIndex) || []; + } } //To-do: Optimize this piece of shit function prepareData() { - tableDataActual = []; - tableDataForecast = []; + tableActualRevenue = []; + tableForecastRevenue = []; + + tableActualEPS = []; + tableForecastEPS = []; let filteredData = analystEstimateList?.filter((item) => item.date >= 2015) ?? []; xData = filteredData?.map(({ date }) => Number(String(date)?.slice(-2))); - if (displayData === "Revenue") { - filteredData?.forEach((item) => { - tableDataActual?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.revenue, - }); - tableDataForecast?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.estimatedRevenueAvg, - numOfAnalysts: item?.numOfAnalysts, - }); + //Revenue Data + filteredData?.forEach((item) => { + tableActualRevenue?.push({ + FY: Number(String(item?.date)?.slice(-2)), + val: item?.revenue, }); - } else if (displayData === "Net Income") { - filteredData?.forEach((item) => { - tableDataActual?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.netIncome, - }); - tableDataForecast?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.estimatedNetIncomeAvg, - numOfAnalysts: item?.numOfAnalysts, - }); + tableForecastRevenue?.push({ + FY: Number(String(item?.date)?.slice(-2)), + val: item?.estimatedRevenueAvg, + numOfAnalysts: item?.numOfAnalysts, }); - } else if (displayData === "EPS") { - let forwardPeStart = false; - filteredData?.forEach((item) => { - const fy = Number(String(item?.date)?.slice(-2)); - const actualVal = item?.eps ?? null; - const forecastVal = item?.estimatedEpsAvg; + }); + //EPS Data + let forwardPeStart = false; + filteredData?.forEach((item) => { + const fy = Number(String(item?.date)?.slice(-2)); + const actualVal = item?.eps ?? null; + const forecastVal = item?.estimatedEpsAvg; - tableDataActual?.push({ - FY: fy, - val: actualVal, - }); - - if (actualVal === null) { - forwardPeStart = true; - } - - const forecastEntry: any = { - FY: fy, - val: forecastVal, - numOfAnalysts: item?.numOfAnalysts, - }; - - // Add forwardPe if the condition is met - if (forwardPeStart && forecastVal !== null) { - forecastEntry.forwardPe = - Math.round((data.getStockQuote.price / forecastVal) * 100) / 100; - } else { - forecastEntry.forwardPe = null; - } - - tableDataForecast?.push(forecastEntry); + tableActualEPS?.push({ + FY: fy, + val: actualVal, }); - } else if (displayData === "EBITDA") { - filteredData?.forEach((item) => { - tableDataActual?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.ebitda, - }); - tableDataForecast?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.estimatedEbitdaAvg, - numOfAnalysts: item?.numOfAnalysts, - }); - }); - } + + if (actualVal === null) { + forwardPeStart = true; + } + + const forecastEntry: any = { + FY: fy, + val: forecastVal, + numOfAnalysts: item?.numOfAnalysts, + }; + + // Add forwardPe if the condition is met + if (forwardPeStart && forecastVal !== null) { + forecastEntry.forwardPe = + Math.round((data.getStockQuote.price / forecastVal) * 100) / 100; + } else { + forecastEntry.forwardPe = null; + } + + tableForecastEPS?.push(forecastEntry); + }); } $: { @@ -279,7 +268,9 @@ analystEstimateList = data?.getAnalystEstimate || []; if (analystEstimateList?.length !== 0) { $analystEstimateComponent = true; - optionsData = getPlotOptions(); + getPlotOptions("Revenue"); + getPlotOptions("EPS"); + prepareData(); } else { $analystEstimateComponent = false; @@ -291,87 +282,11 @@
-
-
- - -
- -
- We analyze insights from various analysts to offer both historical and - future fundamental data forecasts. -
+
+
{#if isLoaded} {#if analystEstimateList?.length !== 0} - - -
-
- -
-
- -
-
- - - - Actual - -
- -
- - - - Analyst Forecast - -
-
-
@@ -397,9 +312,9 @@ - Forecast + Revenue - {#each tableDataForecast as item} + {#each tableForecastRevenue as item} @@ -414,68 +329,53 @@ - Actual + Revenue Growth - {#each tableDataActual as item} + {#each tableActualRevenue as item, index} - {item?.val === "0.00" || - item?.val === null || - item?.val === 0 - ? "-" - : abbreviateNumber(item?.val)} - - {/each} - - - - - % Change - - {#each tableDataActual as item, index} - - {#if index === 0 || tableDataActual?.length === 0} + {#if index === 0 || tableActualRevenue?.length === 0} - {:else if item?.val === null} - {#if tableDataForecast[index]?.val - tableDataForecast[index - 1]?.val > 0} + {#if tableForecastRevenue[index]?.val - tableForecastRevenue[index - 1]?.val > 0} {( - ((tableDataForecast[index]?.val - - tableDataForecast[index - 1]?.val) / - Math.abs(tableDataForecast[index - 1]?.val)) * + ((tableForecastRevenue[index]?.val - + tableForecastRevenue[index - 1]?.val) / + Math.abs( + tableForecastRevenue[index - 1]?.val, + )) * 100 )?.toFixed(2)}%* - {:else if tableDataForecast[index]?.val - tableDataForecast[index - 1]?.val < 0} + {:else if tableForecastRevenue[index]?.val - tableForecastRevenue[index - 1]?.val < 0} {( - ((tableDataForecast[index]?.val - - tableDataForecast[index - 1]?.val) / - Math.abs(tableDataForecast[index - 1]?.val)) * + ((tableForecastRevenue[index]?.val - + tableForecastRevenue[index - 1]?.val) / + Math.abs( + tableForecastRevenue[index - 1]?.val, + )) * 100 )?.toFixed(2)}%* {/if} - {:else if item?.val - tableDataActual[index - 1]?.val > 0} + {:else if item?.val - tableActualRevenue[index - 1]?.val > 0} {( - ((item?.val - tableDataActual[index - 1]?.val) / - Math.abs(tableDataActual[index - 1]?.val)) * + ((item?.val - tableActualRevenue[index - 1]?.val) / + Math.abs(tableActualRevenue[index - 1]?.val)) * 100 )?.toFixed(2)}% - {:else if item?.val - tableDataActual[index - 1]?.val < 0} + {:else if item?.val - tableActualRevenue[index - 1]?.val < 0} {( - ((item?.val - tableDataActual[index - 1]?.val) / - Math.abs(tableDataActual[index - 1]?.val)) * + ((item?.val - tableActualRevenue[index - 1]?.val) / + Math.abs(tableActualRevenue[index - 1]?.val)) * 100 )?.toFixed(2)}% @@ -486,58 +386,114 @@ {/each} - {#if displayData === "EPS"} - - Forward PE + + EPS + + {#each tableForecastEPS as item} + - {#each tableDataForecast as item} - - {item?.forwardPe === "0.00" || - item?.forwardPe === null || - item?.forwardPe === 0 - ? "-" - : abbreviateNumber(item.forwardPe)} - - {/each} - + {item?.val === "0.00" || + item?.val === null || + item?.val === 0 + ? "-" + : abbreviateNumber(item?.val.toFixed(2))} + + {/each} + - - No. Analysts + + EPS Growth + + {#each tableActualEPS as item, index} + - {#each tableDataForecast as item} - - {item?.numOfAnalysts === (null || 0) - ? "-" - : item?.numOfAnalysts} - - {/each} - - {:else} - - 0} + + {( + ((tableForecastEPS[index]?.val - + tableForecastEPS[index - 1]?.val) / + Math.abs(tableForecastEPS[index - 1]?.val)) * + 100 + )?.toFixed(2)}%* + + {:else if tableForecastEPS[index]?.val - tableForecastEPS[index - 1]?.val < 0} + + {( + ((tableForecastEPS[index]?.val - + tableForecastEPS[index - 1]?.val) / + Math.abs(tableForecastEPS[index - 1]?.val)) * + 100 + )?.toFixed(2)}%* + + {/if} + {:else if item?.val - tableActualEPS[index - 1]?.val > 0} + + {( + ((item?.val - tableActualEPS[index - 1]?.val) / + Math.abs(tableActualEPS[index - 1]?.val)) * + 100 + )?.toFixed(2)}% + + {:else if item?.val - tableActualEPS[index - 1]?.val < 0} + + {( + ((item?.val - tableActualEPS[index - 1]?.val) / + Math.abs(tableActualEPS[index - 1]?.val)) * + 100 + )?.toFixed(2)}% + + {:else} + 0.00% + {/if} + + {/each} + + + + + No. Analysts + {#each tableForecastRevenue as item} + + {item?.numOfAnalysts === (null || 0) + ? "-" + : item?.numOfAnalysts} + + {/each} +
@@ -566,6 +522,112 @@
{/if} + +
+
+

Revenue Forecast

+
+
+ {#if optionsRevenue !== null} + + {/if} +
+
+ + + {#each revenueDateList as date} + + {/each} + + + {#each highRevenueList as val} + + {/each} + + {#each avgRevenueList as val} + + {/each} + + {#each lowRevenueList as val} + + {/each} + +
Revenue{date}
High{abbreviateNumber(val)}
Avg{abbreviateNumber(val)}
Low{abbreviateNumber(val)}
+
+
+
+ +
+

EPS Forecast

+
+
+ {#if optionsEPS !== null} + + {/if} +
+
+ + + {#each epsDateList as date} + + {/each} + + + {#each highEPSList as val} + + {/each} + + {#each avgEPSList as val} + + {/each} + + {#each lowEPSList as val} + + {/each} + +
EPS{date}
High{abbreviateNumber(val)}
Avg{abbreviateNumber(val)}
Low{abbreviateNumber(val)}
+
+
+
+
diff --git a/src/routes/stocks/[tickerID]/forecast/+page.svelte b/src/routes/stocks/[tickerID]/forecast/+page.svelte index a18f2bf7..eae1e9cb 100644 --- a/src/routes/stocks/[tickerID]/forecast/+page.svelte +++ b/src/routes/stocks/[tickerID]/forecast/+page.svelte @@ -172,7 +172,6 @@ } function getPieChart() { - const consensusRating = "Buy"; let value; // Determine the value based on the consensus rating switch (consensusRating) { @@ -757,9 +756,7 @@
{#await import("$lib/components/AnalystEstimate.svelte") then { default: Comp }}