From f159335e8ee2b4b4ddcfa36a1a76bacb16564086 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Sat, 7 Sep 2024 11:52:53 +0200 Subject: [PATCH] added forward pe to analystestimates --- src/lib/components/AnalystEstimate.svelte | 149 +++++++++------ .../stocks/[tickerID]/forecast/+page.svelte | 179 +++++++++--------- 2 files changed, 173 insertions(+), 155 deletions(-) diff --git a/src/lib/components/AnalystEstimate.svelte b/src/lib/components/AnalystEstimate.svelte index 576960a4..f520cab3 100644 --- a/src/lib/components/AnalystEstimate.svelte +++ b/src/lib/components/AnalystEstimate.svelte @@ -20,12 +20,12 @@ let xData = []; let optionsData; -let displayData = "Revenue"; + let displayData = "Revenue"; -function findIndex(data) { + function findIndex(data) { const currentYear = new Date().getFullYear(); - return data.findIndex(item => item.date >= currentYear && item.revenue === null); -} + return data.findIndex((item) => item.date >= currentYear && item.revenue === null); + } function changeStatement(event) { displayData = event.target.value; @@ -50,7 +50,6 @@ function findIndex(data) { let tableDataActual = []; let tableDataForecast = []; - function getPlotOptions() { let dates = []; let valueList = []; @@ -58,58 +57,54 @@ function findIndex(data) { let lowList = []; let highList = []; - let filteredData = analystEstimateList?.filter((item) => item.date >= 2019) ?? []; const stopIndex = findIndex(filteredData); - - if (filteredData) { - filteredData.forEach((item, index) => { - const date = item.date?.toString().slice(-2); - const isBeforeStopIndex = index < stopIndex - 1; - const isAfterStartIndex = index >= stopIndex - 2; - dates.push(`FY${date}`); - switch (displayData) { - case "Revenue": - valueList.push(isBeforeStopIndex ? item.revenue : null); - avgList.push(isAfterStartIndex ? item.estimatedRevenueAvg : null); - lowList.push(isAfterStartIndex ? item.estimatedRevenueLow : null); - highList.push(isAfterStartIndex ? item.estimatedRevenueHigh : null); - break; - case "Net Income": - valueList.push(isBeforeStopIndex ? item.netIncome : null); - avgList.push(isAfterStartIndex ? item.estimatedNetIncomeAvg : null); - lowList.push(isAfterStartIndex ? item.estimatedNetIncomeLow : null); - highList.push(isAfterStartIndex ? item.estimatedNetIncomeHigh : null); - break; - case "EBITDA": - valueList.push(isBeforeStopIndex ? item.ebitda : null); - avgList.push(isAfterStartIndex ? item.estimatedEbitdaAvg : null); - lowList.push(isAfterStartIndex ? item.estimatedEbitdaLow : null); - highList.push(isAfterStartIndex ? item.estimatedEbitdaHigh : null); - break; - case "EPS": - valueList.push(isBeforeStopIndex ? item.eps : null); - avgList.push(isAfterStartIndex ? item.estimatedEpsAvg : null); - lowList.push(isAfterStartIndex ? item.estimatedEpsLow : null); - highList.push(isAfterStartIndex ? item.estimatedEpsHigh : null); - break; - default: - break; - } - }); + if (filteredData) { + filteredData.forEach((item, index) => { + const date = item.date?.toString().slice(-2); + const isBeforeStopIndex = index < stopIndex - 1; + const isAfterStartIndex = index >= stopIndex - 2; + dates.push(`FY${date}`); + switch (displayData) { + case "Revenue": + valueList.push(isBeforeStopIndex ? item.revenue : null); + avgList.push(isAfterStartIndex ? item.estimatedRevenueAvg : null); + lowList.push(isAfterStartIndex ? item.estimatedRevenueLow : null); + highList.push(isAfterStartIndex ? item.estimatedRevenueHigh : null); + break; + case "Net Income": + valueList.push(isBeforeStopIndex ? item.netIncome : null); + avgList.push(isAfterStartIndex ? item.estimatedNetIncomeAvg : null); + lowList.push(isAfterStartIndex ? item.estimatedNetIncomeLow : null); + highList.push(isAfterStartIndex ? item.estimatedNetIncomeHigh : null); + break; + case "EBITDA": + valueList.push(isBeforeStopIndex ? item.ebitda : null); + avgList.push(isAfterStartIndex ? item.estimatedEbitdaAvg : null); + lowList.push(isAfterStartIndex ? item.estimatedEbitdaLow : null); + highList.push(isAfterStartIndex ? item.estimatedEbitdaHigh : null); + break; + case "EPS": + valueList.push(isBeforeStopIndex ? item.eps : null); + avgList.push(isAfterStartIndex ? item.estimatedEpsAvg : null); + lowList.push(isAfterStartIndex ? item.estimatedEpsLow : null); + highList.push(isAfterStartIndex ? item.estimatedEpsHigh : null); + break; - } - try { - const lastValue = valueList[stopIndex-2]; - avgList[stopIndex-2] = lastValue; - lowList[stopIndex-2] = lastValue; - highList[stopIndex-2] = lastValue; - } catch(e) { - console.log(e) + default: + break; + } + }); + } + try { + const lastValue = valueList[stopIndex - 2]; + avgList[stopIndex - 2] = lastValue; + lowList[stopIndex - 2] = lastValue; + highList[stopIndex - 2] = lastValue; + } catch (e) { + console.log(e); } - - // Normalize the data if needed (not required in this case, but leaving it here for reference) const { unit, denominator } = normalizer(Math.max(...valueList, ...avgList) ?? 0); @@ -171,7 +166,7 @@ function findIndex(data) { color: "#fff", // Change line plot color to green }, lineStyle: { - type: "dashed" // Set the line type to dashed + type: "dashed", // Set the line type to dashed }, showSymbol: false, // Show symbols for line plot points }, @@ -179,11 +174,11 @@ function findIndex(data) { name: "Low", data: lowList, type: "line", - itemStyle: { + itemStyle: { color: "#3CB2EF", // Change line plot color to green }, lineStyle: { - type: "dashed" // Set the line type to dashed + type: "dashed", // Set the line type to dashed }, showSymbol: false, // Show symbols for line plot points }, @@ -195,7 +190,7 @@ function findIndex(data) { color: "#3CB2EF", // Change line plot color to green }, lineStyle: { - type: "dashed" // Set the line type to dashed + type: "dashed", // Set the line type to dashed }, showSymbol: false, // Show symbols for line plot points }, @@ -238,16 +233,35 @@ function findIndex(data) { }); }); } 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; + tableDataActual?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.eps ?? null, + FY: fy, + val: actualVal, }); - tableDataForecast?.push({ - FY: Number(String(item?.date)?.slice(-2)), - val: item?.estimatedEpsAvg, + + 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); }); } else if (displayData === "EBITDA") { filteredData?.forEach((item) => { @@ -388,6 +402,17 @@ function findIndex(data) { {/each} + {#if displayData === "EPS"} + + Forward PE + {#each tableDataForecast as item} + + {item?.forwardPe === "0.00" || item?.forwardPe === null || item?.forwardPe === 0 ? "-" : abbreviateNumber(item.forwardPe)} + + {/each} + + {/if} + No. Analysts {#each tableDataForecast as item} diff --git a/src/routes/stocks/[tickerID]/forecast/+page.svelte b/src/routes/stocks/[tickerID]/forecast/+page.svelte index 7f219414..8e546775 100644 --- a/src/routes/stocks/[tickerID]/forecast/+page.svelte +++ b/src/routes/stocks/[tickerID]/forecast/+page.svelte @@ -8,20 +8,18 @@ let changeNetIncome = 0; let changeEBITDA = 0; let changeEPS = 0; -function findIndex(data) { + function findIndex(data) { const currentYear = new Date().getFullYear(); - return data?.findIndex(item => item?.date >= currentYear && item?.revenue === null); -} - - -if(data?.getAnalystEstimate?.length !== 0) { - index = findIndex(data?.getAnalystEstimate); - changeRevenue = ((data?.getAnalystEstimate[index-1]?.estimatedRevenueAvg/data?.getAnalystEstimate[index-2]?.revenue-1)*100) - changeNetIncome = ((data?.getAnalystEstimate[index-1]?.estimatedNetIncomeAvg/data?.getAnalystEstimate[index-2]?.netIncome-1)*100) - changeEBITDA = ((data?.getAnalystEstimate[index-1]?.estimatedEbitdaAvg/data?.getAnalystEstimate[index-2]?.ebitda-1)*100) - changeEPS = ((data?.getAnalystEstimate[index-1]?.estimatedEpsAvg/data?.getAnalystEstimate[index-2]?.eps-1)*100) -} + return data?.findIndex((item) => item?.date >= currentYear && item?.revenue === null); + } + if (data?.getAnalystEstimate?.length !== 0) { + index = findIndex(data?.getAnalystEstimate); + changeRevenue = (data?.getAnalystEstimate[index - 1]?.estimatedRevenueAvg / data?.getAnalystEstimate[index - 2]?.revenue - 1) * 100; + changeNetIncome = (data?.getAnalystEstimate[index - 1]?.estimatedNetIncomeAvg / data?.getAnalystEstimate[index - 2]?.netIncome - 1) * 100; + changeEBITDA = (data?.getAnalystEstimate[index - 1]?.estimatedEbitdaAvg / data?.getAnalystEstimate[index - 2]?.ebitda - 1) * 100; + changeEPS = (data?.getAnalystEstimate[index - 1]?.estimatedEpsAvg / data?.getAnalystEstimate[index - 2]?.eps - 1) * 100; + } @@ -50,83 +48,78 @@ if(data?.getAnalystEstimate?.length !== 0) {
- -

- Financial Forecast this Year -

+

Financial Forecast this Year

{#if data?.getAnalystEstimate?.length !== 0} -
-
- -
-
- {abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedRevenueAvg,true)} -
-
- - {abbreviateNumber(changeRevenue?.toFixed(1))}% -
-
-
- from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.revenue)} -
-
-
- -
-
- {abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedNetIncomeAvg,true)} -
-
- - {abbreviateNumber(changeNetIncome?.toFixed(1))}% -
-
-
- from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.netIncome,true)} -
-
-
- -
-
- {abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedEbitdaAvg,true)} -
-
- - {abbreviateNumber(changeEBITDA?.toFixed(2))}% -
-
-
- from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.ebitda,true)} -
-
-
- -
-
- {data?.getAnalystEstimate[index-1]?.estimatedEpsAvg} -
-
- - {abbreviateNumber(changeEPS?.toFixed(1))}% -
-
-
- from {data?.getAnalystEstimate[index-2]?.eps} -
-
-
- - +
+
+ +
+
+ {abbreviateNumber(data?.getAnalystEstimate[index - 1]?.estimatedRevenueAvg, true)} +
+
+ + {abbreviateNumber(changeRevenue?.toFixed(1))}% +
+
+
+ from {abbreviateNumber(data?.getAnalystEstimate[index - 2]?.revenue)} +
+
+
+ +
+
+ {abbreviateNumber(data?.getAnalystEstimate[index - 1]?.estimatedNetIncomeAvg, true)} +
+
+ + {abbreviateNumber(changeNetIncome?.toFixed(1))}% +
+
+
+ from {abbreviateNumber(data?.getAnalystEstimate[index - 2]?.netIncome, true)} +
+
+
+ +
+
+ {abbreviateNumber(data?.getAnalystEstimate[index - 1]?.estimatedEbitdaAvg, true)} +
+
+ + {abbreviateNumber(changeEBITDA?.toFixed(2))}% +
+
+
+ from {abbreviateNumber(data?.getAnalystEstimate[index - 2]?.ebitda, true)} +
+
+
+ +
+
+ {data?.getAnalystEstimate[index - 1]?.estimatedEpsAvg} +
+
+ + {abbreviateNumber(changeEPS?.toFixed(1))}% +
+
+
+ from {data?.getAnalystEstimate[index - 2]?.eps} +
+
+
{#await import("$lib/components/AnalystEstimate.svelte") then { default: Comp }} @@ -134,13 +127,13 @@ if(data?.getAnalystEstimate?.length !== 0) { {/await}
{:else} -
- +
+ No analyst forecast available for {$displayCompanyName}. -
+
{/if} - -