update forecast overview page

This commit is contained in:
MuslemRahimi 2024-08-31 13:35:47 +02:00
parent f8ed49b3d4
commit defd8a9283
4 changed files with 113 additions and 39 deletions

View File

@ -1,8 +1,20 @@
<script lang="ts"> <script lang="ts">
import { numberOfUnreadNotification, displayCompanyName, stockTicker, analystEstimateComponent, currentPortfolioPrice } from "$lib/store"; import { numberOfUnreadNotification, displayCompanyName, stockTicker, analystEstimateComponent } from "$lib/store";
import { abbreviateNumber } from "$lib/utils";
import Lazy from "$lib/components/Lazy.svelte"; import Lazy from "$lib/components/Lazy.svelte";
export let data; export let data;
function findIndex(data) {
const currentYear = new Date().getFullYear();
return data.findIndex(item => item.date >= currentYear && item.revenue === null);
}
const index = findIndex(data?.getAnalystEstimate);
const changeRevenue = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedRevenueAvg/data?.getAnalystEstimate[index-2]?.revenue-1)*100))?.toFixed(1)
const changeNetIncome = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedNetIncomeAvg/data?.getAnalystEstimate[index-2]?.netIncome-1)*100))?.toFixed(1)
const changeEBITDA = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedEbitdaAvg/data?.getAnalystEstimate[index-2]?.ebitda-1)*100)?.toFixed(1))
const changeEPS = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedEpsAvg/data?.getAnalystEstimate[index-2]?.eps-1)*100))?.toFixed(1)
</script> </script>
<svelte:head> <svelte:head>
@ -31,6 +43,84 @@
<div class="flex justify-center m-auto h-full overflow-hidden w-full"> <div class="flex justify-center m-auto h-full overflow-hidden w-full">
<div class="relative flex justify-center items-center overflow-hidden w-full"> <div class="relative flex justify-center items-center overflow-hidden w-full">
<div class="sm:p-7 w-full m-auto mt-2 sm:mt-0"> <div class="sm:p-7 w-full m-auto mt-2 sm:mt-0">
<h2 class="mt-5 text-xl sm:text-2xl text-gray-200 font-bold mb-4">
Financial Forecast this Year
</h2>
<div class="mb-4 grid grid-cols-2 grid-rows-1 divide-gray-500 rounded-lg border border-gray-600 bg-[#272727] shadow md:grid-cols-4 md:grid-rows-1 md:divide-x">
<div class="p-4 bp:p-5 sm:p-6">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
Revenue
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedRevenueAvg,true)}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeRevenue > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeRevenue}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.revenue)}
</div>
</div>
<div class="p-4 bp:p-5 sm:p-6 border-l border-contrast md:border-0">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
Net Income
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedNetIncomeAvg,true)}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeNetIncome > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeNetIncome}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.netIncome,true)}
</div>
</div>
<div class="p-4 bp:p-5 sm:p-6 border-t border-contrast md:border-0">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
EBITDA
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedEbitdaAvg,true)}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeEBITDA > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeEBITDA}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.ebitda,true)}
</div>
</div>
<div class="p-4 bp:p-5 sm:p-6 border-t border-contrast md:border-0 border-l border-contrast md:border-0">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
EPS
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{data?.getAnalystEstimate[index-1]?.estimatedEpsAvg}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeEPS > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeEPS}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {data?.getAnalystEstimate[index-2]?.eps}
</div>
</div>
</div>
<Lazy> <Lazy>
<div class="w-full m-auto sm:pb-6 sm:pt-6 {!$analystEstimateComponent ? 'hidden' : ''}"> <div class="w-full m-auto sm:pb-6 sm:pt-6 {!$analystEstimateComponent ? 'hidden' : ''}">
{#await import("$lib/components/AnalystEstimate.svelte") then { default: Comp }} {#await import("$lib/components/AnalystEstimate.svelte") then { default: Comp }}

View File

@ -1,36 +1,32 @@
import { getCache, setCache } from '$lib/store'; import { getCache, setCache } from "$lib/store";
export const load = async ({ parent, params }) => { export const load = async ({ parent, params }) => {
const getAnalystEstimate = async () => {
const getAnalystTickerHistory = async () => {
let output; let output;
const cachedData = getCache(params.tickerID, 'getAnalystTickerHistory'); const cachedData = getCache(params.tickerID, "getAnalystEstimate");
if (cachedData) { if (cachedData) {
output = cachedData; output = cachedData;
} else { } else {
const { apiURL, apiKey } = await parent(); const { apiURL, apiKey } = await parent();
const postData = { const postData = {
ticker: params.tickerID ticker: params.tickerID,
}; };
// make the POST request to the endpoint // make the POST request to the endpoint
const response = await fetch(apiURL + '/analyst-ticker-history', { const response = await fetch(apiURL + "/analyst-estimate", {
method: 'POST', method: "POST",
headers: { headers: {
"Content-Type": "application/json", "X-API-KEY": apiKey "Content-Type": "application/json",
"X-API-KEY": apiKey,
}, },
body: JSON.stringify(postData) body: JSON.stringify(postData),
}); });
output = await response.json(); output = await response.json();
setCache(params.tickerID, output, 'getAnalystTickerHistory'); setCache(params.tickerID, output, "getAnalystEstimate");
} }
return output; return output;
@ -38,6 +34,6 @@ export const load = async ({ parent, params }) => {
// Make sure to return a promise // Make sure to return a promise
return { return {
getAnalystTickerHistory: await getAnalystTickerHistory() getAnalystEstimate: await getAnalystEstimate(),
}; };
}; };

View File

@ -3,21 +3,12 @@
import ReturnCard from "$lib/components/ReturnCard.svelte"; import ReturnCard from "$lib/components/ReturnCard.svelte";
import { numberOfUnreadNotification, displayCompanyName, screenWidth, stockTicker, revenueSegmentationComponent } from "$lib/store"; import { numberOfUnreadNotification, displayCompanyName, screenWidth, stockTicker, revenueSegmentationComponent } from "$lib/store";
import { abbreviateNumber } from "$lib/utils"; import { abbreviateNumber } from "$lib/utils";
import RevenueSegmentation from "$lib/components/RevenueSegmentation.svelte";
export let data; export let data;
let quantStats = {}; let quantStats = {};
let stockQuote;
let marketCap = "-";
let currentPrice = 0;
let previousClose = "-";
let volume = "-";
let eps = "-";
let pe = "-";
let alpha = "-";
let beta = "-";
// Function to check if a date is today or yesterday, adjusting for weekends // Function to check if a date is today or yesterday, adjusting for weekends
function ongoingDD(dateString: string) { function ongoingDD(dateString: string) {
@ -75,7 +66,6 @@ if (progressYearPriceValue < currentPrice) {
stockQuote = data?.getStockQuote;
quantStats = data?.getQuantStats ?? {}; quantStats = data?.getQuantStats ?? {};
@ -218,9 +208,7 @@ updateYearRange()
<!--Start RevenueSegmentation--> <!--Start RevenueSegmentation-->
<Lazy> <Lazy>
<div class="w-full pt-10 sm:pb-6 sm:pt-6 m-auto {!$revenueSegmentationComponent ? 'hidden' : ''}"> <div class="w-full pt-10 sm:pb-6 sm:pt-6 m-auto {!$revenueSegmentationComponent ? 'hidden' : ''}">
{#await import("$lib/components/RevenueSegmentation.svelte") then { default: Comp }} <RevenueSegmentation apiURL={data?.apiURL} apiKey={data?.apiKey} userTier={data?.user?.tier} />
<svelte:component this={Comp} apiURL={data?.apiURL} apiKey={data?.apiKey} userTier={data?.user?.tier} />
{/await}
</div> </div>
</Lazy> </Lazy>
<!--End RevenueSegmentation--> <!--End RevenueSegmentation-->
@ -230,7 +218,7 @@ updateYearRange()
{#if $stockTicker in quantStats && Object.keys(quantStats[$stockTicker]).length > 0} {#if $stockTicker in quantStats && Object.keys(quantStats[$stockTicker]).length > 0}
<h3 class="text-start w-full mt-8 mb-2 text-lg sm:text-2xl font-bold text-white"> <h3 class="text-start w-full mb-2 text-lg sm:text-2xl font-bold text-white">
Worst 10 Drawdowns of {$stockTicker} Worst 10 Drawdowns of {$stockTicker}
</h3> </h3>
<div class="w-full overflow-x-scroll"> <div class="w-full overflow-x-scroll">