frontend/src/lib/components/TARating.svelte
2024-10-28 22:22:50 +01:00

267 lines
8.6 KiB
Svelte

<script lang="ts">
import {
taRatingComponent,
stockTicker,
etfTicker,
cryptoTicker,
assetType,
getCache,
setCache,
} from "$lib/store";
import SignalBar from "$lib/components/SignalBar.svelte";
import InfoModal from "$lib/components/InfoModal.svelte";
export let data;
let rawData = [];
let isLoaded = false;
let signalList = [];
let showFullStats = false;
let overallSignal = "n/a";
let buyCount = 0;
let sellCount = 0;
let neutralCount = 0;
const modalContent = `
Momentum indicators gauge the speed at which a financial instrument's price is changing, indicating the strength of its recent price movements.<br><br>
On the other hand, trend indicators help identify the direction in which the price of an asset is moving over time, highlighting whether it's in an upward, downward, or sideways trend.<br><br>
Together, these indicators assist in evaluating the overall market sentiment and potential future price movements.
`;
async function getTaRating(ticker) {
const cachedData = getCache(ticker, "getTaRating");
if (cachedData) {
rawData = cachedData;
} else {
try {
const response = await fetch("/api/ticker-data", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ ticker: ticker, path: "stock-rating" }),
});
rawData = await response?.json();
setCache(ticker, rawData, "getTaRating");
} catch (error) {
console.error("Failed to fetch swap data:", error);
rawData = {};
}
}
if (Object?.keys(rawData)?.length !== 0) {
$taRatingComponent = true;
} else {
$taRatingComponent = false;
}
}
async function updateData() {
if (
($assetType === "stock"
? $stockTicker
: $assetType === "etf"
? $etfTicker
: $cryptoTicker) &&
typeof window !== "undefined"
) {
isLoaded = false;
const ticker =
$assetType === "stock"
? $stockTicker
: $assetType === "etf"
? $etfTicker
: $cryptoTicker;
try {
await getTaRating(ticker);
showFullStats = false;
overallSignal = rawData?.overallSignal;
signalList = rawData?.signalList || [];
buyCount = 0;
sellCount = 0;
neutralCount = 0;
signalList?.forEach((item) => {
switch (item?.signal) {
case "Strong Buy":
case "Buy":
buyCount++;
break;
case "Sell":
case "Strong Sell":
sellCount++;
break;
default:
neutralCount++;
}
});
isLoaded = true;
} catch (error) {
console.error("Error fetching data:", error);
}
}
}
$: if ($assetType || $stockTicker || $etfTicker || $cryptoTicker) {
updateData();
}
</script>
<section class="overflow-hidden w-full">
<main>
<div class="flex flex-row items-center">
<label
for="technicalIndicatorInfo"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
>
TA Indicators
</label>
<InfoModal
title={"TA Indicators"}
content={modalContent}
id={"technicalIndicatorInfo"}
/>
</div>
{#if isLoaded}
{#if signalList?.length !== 0}
{#if overallSignal !== "n/a"}
<div class="text-white text-[1rem] sm:text-lg mt-3 mb-8 text-start">
Out of 11 indicators, <span class="font-semibold text-[#00FC50]"
>{buyCount}</span
>
indicates a Buy,
<span class="font-semibold text-[#F8901E]">{neutralCount}</span> are
Neutral and
<span class="font-semibold text-[#FF2F1F]">{sellCount}</span>
indicate a Sell. On average, the signal is to
{#if overallSignal === "Buy" || overallSignal === "Strong Buy"}
<span class="text-[#00FC50] sm:font-medium">
<svg
class="w-7 h-7 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><g
fill="none"
stroke="#00FC50"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2.5"
><path d="m3 17l6-6l4 4l8-8" /><path d="M17 7h4v4" /></g
></svg
>
Buy.
</span>
{:else if overallSignal === "Neutral"}
<span class="text-[#E57C34] sm:font-medium">
<svg
class="w-7 h-7 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path fill="#e57c34" d="m22 12l-4-4v3H3v2h15v3l4-4Z" /></svg
>
Hold.
</span>
{:else if overallSignal === "Sell" || overallSignal === "Strong Sell"}
<span class="text-[#FF2F1F] sm:font-medium">
<svg
class="w-7 h-7 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 256 256"
><path
fill="#ff2f1f"
d="M244 136v64a12 12 0 0 1-12 12h-64a12 12 0 0 1 0-24h35l-67-67l-31.51 31.52a12 12 0 0 1-17 0l-72-72a12 12 0 0 1 17-17L96 127l31.51-31.52a12 12 0 0 1 17 0L220 171v-35a12 12 0 0 1 24 0Z"
/></svg
>
Sell.
</span>
{:else}
<span class="text-[#FF2F1F] sm:font-medium"> n/a. </span>
{/if}
</div>
{/if}
<!--Start Momentum Indicators-->
<div class="w-full overflow-x-scroll">
<table class="table table-sm table-compact w-full mb-5 mt-5">
<!-- head -->
<thead>
<tr>
<th
class="text-white text-sm font-medium bg-[#09090B] font-semibold"
>Name</th
>
<th
class="text-white text-sm font-medium bg-[#09090B] font-semibold text-end"
>Value</th
>
<th
class="text-white text-sm font-medium bg-[#09090B] font-semibold text-end"
>Signal</th
>
</tr>
</thead>
<tbody>
{#each showFullStats ? signalList : signalList?.slice(0, 3) as item, index}
<tr
class="border-y border-gray-800 odd:bg-[#27272A] sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] bg-[#09090B] border-b-[#09090B] {index ===
2 &&
!showFullStats &&
signalList?.length > 2
? 'opacity-[0.3]'
: ''}"
>
<td class="text-white text-sm sm:text-[1rem]">
{item?.name}
</td>
<td class="text-white text-end">
<span class="text-white text-sm sm:text-[1rem] font-medium">
{item?.value}
</span>
</td>
<td class="text-white">
<SignalBar signal={item?.signal} />
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<label
on:click={() => (showFullStats = !showFullStats)}
class="{signalList?.length < 4
? 'hidden'
: ''} cursor-pointer m-auto flex justify-center items-center mt-5"
>
<svg
class="w-10 h-10 transform {showFullStats ? 'rotate-180' : ''} "
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path
fill="#2A323C"
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm0 13.5L7.5 11l1.42-1.41L12 12.67l3.08-3.08L16.5 11L12 15.5z"
/></svg
>
</label>
<!--End Momentum Indicators-->
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-[#09090B] rounded-xl h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span class="loading loading-spinner loading-md text-gray-400"
></span>
</label>
</div>
</div>
{/if}
</main>
</section>