From a7890569481d5839b3898b53f2a6099852a5dc55 Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Sat, 28 Dec 2024 01:37:30 +0100 Subject: [PATCH] update sector flow page --- src/lib/components/Table/TableHeader.svelte | 20 +- src/routes/sector-flow/+page.server.ts | 4 +- src/routes/sector-flow/+page.svelte | 223 +++++++++++++++++++- 3 files changed, 234 insertions(+), 13 deletions(-) diff --git a/src/lib/components/Table/TableHeader.svelte b/src/lib/components/Table/TableHeader.svelte index 2acae5a2..68cd8913 100644 --- a/src/lib/components/Table/TableHeader.svelte +++ b/src/lib/components/Table/TableHeader.svelte @@ -3,6 +3,22 @@ export let sortOrders = {}; export let sortData; + // Local sort orders specific to this table + let localSortOrders = { ...sortOrders }; + + // Handle sorting within this table + function handleSort(key) { + const currentOrder = localSortOrders[key]?.order || null; + const newOrder = + currentOrder === "asc" ? "desc" : currentOrder === "desc" ? null : "asc"; + localSortOrders = { ...localSortOrders, [key]: { order: newOrder } }; + + // Notify parent with the updated sort state + if (sortData) { + sortData(key, newOrder); + } + } + const SortIcon = ({ sortOrder }) => ` {#each columns as column} sortData(column.key)} + on:click={() => handleSort(column.key)} class="cursor-pointer select-none text-white font-semibold text-sm whitespace-nowrap {column.align === 'right' ? 'text-end' : 'text-start'}" > {column.label} - {@html SortIcon({ sortOrder: sortOrders[column.key].order })} + {@html SortIcon({ sortOrder: localSortOrders[column.key]?.order })} {/each} diff --git a/src/routes/sector-flow/+page.server.ts b/src/routes/sector-flow/+page.server.ts index 721754e7..12a8e793 100644 --- a/src/routes/sector-flow/+page.server.ts +++ b/src/routes/sector-flow/+page.server.ts @@ -10,8 +10,8 @@ export const load = async ({ locals }) => { }, }); - let output = await response?.json(); - output = user?.tier !== "Pro" ? output?.slice(0, 6) : output; + const output = await response?.json(); + //output = user?.tier !== "Pro" ? output?.slice(0, 6) : output; return output; }; diff --git a/src/routes/sector-flow/+page.svelte b/src/routes/sector-flow/+page.svelte index a44276be..25e823a9 100644 --- a/src/routes/sector-flow/+page.svelte +++ b/src/routes/sector-flow/+page.svelte @@ -5,6 +5,7 @@ import UpgradeToPro from "$lib/components/UpgradeToPro.svelte"; import { abbreviateNumberWithColor, sectorNavigation } from "$lib/utils"; import * as HoverCard from "$lib/components/shadcn/hover-card/index.js"; + /* import { Chart } from "svelte-echarts"; import { init, use } from "echarts/core"; @@ -13,13 +14,19 @@ import { CanvasRenderer } from "echarts/renderers"; use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]); + */ export let data; - let rawData = data?.getData || []; - let originalData = [...rawData]; // Unaltered copy of raw data + let sectorData = data?.getData?.sectorData || []; + let topSectorTickers = data?.getData?.topSectorTickers || {}; + let selectedSector = "Technology"; + let originalData = [...sectorData]; // Unaltered copy of raw data - let stockList = rawData?.slice(0, 50) ?? []; + let stockList = sectorData ?? []; + + let originalTopTickers = [...topSectorTickers[selectedSector]]; + let displayTopTickers = topSectorTickers[selectedSector]; $: columns = [ { key: "ticker", label: "Symbol", align: "left" }, @@ -34,6 +41,7 @@ ]; $: sortOrders = { + rank: { order: "none", type: "number" }, date: { order: "none", type: "date" }, ticker: { order: "none", type: "string" }, name: { order: "none", type: "string" }, @@ -46,6 +54,34 @@ avg30_put_volume: { order: "none", type: "number" }, }; + $: sortTopTickersOrders = { + rank: { order: "none", type: "number" }, + ticker: { order: "none", type: "string" }, + name: { order: "none", type: "string" }, + price: { order: "none", type: "number" }, + changesPercentage: { order: "none", type: "number" }, + netPremium: { order: "none", type: "number" }, + netCallPremium: { order: "none", type: "number" }, + netPutPremium: { order: "none", type: "number" }, + gexRatio: { order: "none", type: "number" }, + gexNetChange: { order: "none", type: "number" }, + ivRank: { order: "none", type: "number" }, + }; + + $: topColumns = [ + { key: "rank", label: "Rank", align: "left" }, + { key: "ticker", label: "Symbol", align: "left" }, + { key: "name", label: "Name", align: "left" }, + { key: "price", label: "Price", align: "right" }, + { key: "changesPercentage", label: "% Change", align: "right" }, + { key: "netPremium", label: "Net Prem", align: "right" }, + { key: "netCallPremium", label: "Net Call Prem", align: "right" }, + { key: "netPutPremium", label: "Net Put Prem", align: "right" }, + { key: "gexRatio", label: "Gex Ratio", align: "right" }, + { key: "gexNetChange", label: "Gex Change", align: "right" }, + { key: "ivRank", label: "IV Rank", align: "right" }, + ]; + const sortData = (key) => { // Reset all other keys to 'none' except the current key for (const k in sortOrders) { @@ -64,7 +100,7 @@ // Reset to original data when 'none' and stop further sorting if (sortOrder === "none") { - originalData = [...rawData]; // Reset originalData to rawData + originalData = [...sectorData]; // Reset originalData to sectorData stockList = originalData?.slice(0, 50); // Reset displayed data return; } @@ -103,9 +139,68 @@ stockList = [...originalData].sort(compareValues)?.slice(0, 50); }; + const sortTopTickers = (key) => { + // Reset all other keys to 'none' except the current key + for (const k in sortOrders) { + if (k !== key) { + sortOrders[k].order = "none"; + } + } + + // Cycle through 'none', 'asc', 'desc' for the clicked key + const orderCycle = ["none", "asc", "desc"]; + + const currentOrderIndex = orderCycle.indexOf(sortOrders[key].order); + sortOrders[key].order = + orderCycle[(currentOrderIndex + 1) % orderCycle.length]; + const sortOrder = sortOrders[key].order; + + // Reset to original data when 'none' and stop further sorting + if (sortOrder === "none") { + originalTopTickers = [...topSectorTickers[selectedSector]]; // Reset originalTopTickers to sectorData + displayTopTickers = originalTopTickers; + return; + } + + // Define a generic comparison function + const compareValues = (a, b) => { + const { type } = sortOrders[key]; + let valueA, valueB; + + switch (type) { + case "date": + valueA = new Date(a[key]); + valueB = new Date(b[key]); + break; + case "string": + valueA = a[key].toUpperCase(); + valueB = b[key].toUpperCase(); + return sortOrder === "asc" + ? valueA.localeCompare(valueB) + : valueB.localeCompare(valueA); + case "number": + default: + valueA = parseFloat(a[key]); + valueB = parseFloat(b[key]); + break; + } + + if (sortOrder === "asc") { + return valueA < valueB ? -1 : valueA > valueB ? 1 : 0; + } else { + return valueA > valueB ? -1 : valueA < valueB ? 1 : 0; + } + }; + + // Sort using the generic comparison function + displayTopTickers = [...originalTopTickers] + .sort(compareValues) + ?.slice(0, 50); + }; + /* function getPlotOptions() { - const historyData = rawData?.at(1)?.premTickHistory; - console.log(rawData?.at(1)); + const historyData = sectorData?.at(1)?.premTickHistory; + console.log(sectorData?.at(1)); const dates = historyData.map((item) => item.tape_time); const priceList = historyData.map((item) => item.close); const netCallPremList = historyData.map((item) => item.net_call_premium); @@ -235,7 +330,8 @@ }; } - let optionsData = rawData ? getPlotOptions() : null; + let optionsData = null; //sectorData ? getPlotOptions() : null; + */ @@ -313,7 +409,7 @@
@@ -467,7 +563,7 @@ - + + + +
+

+ Top 10 {selectedSector} Tickers by Net Premium +

+
+ + + + + + {#each displayTopTickers as item, index} + + + + + + + + + + + + + + + + + + + + {/each} + +
+ {item?.rank} + + + + listItem?.title === item?.name, + )?.link} + class="sm:hover:underline sm:hover:underline-offset-4 text-white" + > + {item?.name} + + + {item?.price} + + {item?.changesPercentage}% + + {@html abbreviateNumberWithColor( + item?.netPremium, + false, + true, + )} + + {@html abbreviateNumberWithColor( + item?.netCallPremium, + false, + true, + )} + + {@html abbreviateNumberWithColor( + item?.netPutPremium, + false, + true, + )} + + {item?.gexRatio} + + {@html abbreviateNumberWithColor( + item?.gexNetChange, + false, + true, + )} + + {item?.ivRank} +
+