From ea9fe4c868e4f84c53829632a9a652a521e0b35d Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Thu, 6 Feb 2025 11:10:15 +0100 Subject: [PATCH] update market flow --- src/lib/components/Options/Volatility.svelte | 13 + src/routes/market-flow/+page.svelte | 280 ++++++++----------- 2 files changed, 131 insertions(+), 162 deletions(-) diff --git a/src/lib/components/Options/Volatility.svelte b/src/lib/components/Options/Volatility.svelte index 240ad740..aae4e767 100644 --- a/src/lib/components/Options/Volatility.svelte +++ b/src/lib/components/Options/Volatility.svelte @@ -414,6 +414,19 @@
{#if options !== null}
+
+ {#each ["3M", "6M", "1Y"] as item} + + {/each} +
+
{:else} diff --git a/src/routes/market-flow/+page.svelte b/src/routes/market-flow/+page.svelte index df5af888..19bb25e1 100644 --- a/src/routes/market-flow/+page.svelte +++ b/src/routes/market-flow/+page.svelte @@ -32,12 +32,15 @@ let isLoading = false; let optionsData = null; //let sectorData = data?.getData?.sectorData || []; - let topSectorTickers = data?.getData?.topSectorTickers || {}; - let marketTideData = data?.getData?.marketTide || {}; - let selectedSector = "SPY"; + let topPosNetPremium = data?.getData?.topPosNetPremium || []; + let topNegNetPremium = data?.getData?.topNegNetPremium || {}; - let originalTopTickers = [...topSectorTickers[selectedSector]]; - let displayTopTickers = topSectorTickers[selectedSector]; + let marketTideData = data?.getData?.marketTide || {}; + let originalPosTickers = topPosNetPremium; + let displayPosTickers = topPosNetPremium; + + let originalNegTickers = topNegNetPremium; + let displayNegTickers = topNegNetPremium; function findLastNonNull(dataArray, key) { for (let i = dataArray.length - 1; i >= 0; i--) { @@ -89,15 +92,12 @@ changesPercentage: { order: "none", type: "number" }, call_volume: { order: "none", type: "number" }, put_volume: { order: "none", type: "number" }, - premium_ratio: { order: "none", type: "number" }, - avg30_call_volume: { order: "none", type: "string" }, - avg30_put_volume: { order: "none", type: "number" }, - netPremium: { order: "none", type: "number" }, - netCallPremium: { order: "none", type: "number" }, - netPutPremium: { order: "none", type: "number" }, + net_premium: { order: "none", type: "number" }, + net_call_premium: { order: "none", type: "number" }, + net_put_premium: { order: "none", type: "number" }, call_premium: { order: "none", type: "number" }, put_premium: { order: "none", type: "number" }, - ivRank: { order: "none", type: "number" }, + iv_rank: { order: "none", type: "number" }, }; $: topColumns = [ @@ -106,13 +106,13 @@ { 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: "ivRank", label: "IV Rank", align: "right" }, + { key: "net_premium", label: "Net Prem", align: "right" }, + { key: "net_call_premium", label: "Net Call Prem", align: "right" }, + { key: "net_put_premium", label: "Net Put Prem", align: "right" }, + { key: "iv_rank", label: "IV Rank", align: "right" }, ]; - const sortTopTickers = (key) => { + const sortPosTickers = (key) => { // Reset all other keys to 'none' except the current key for (const k in sortOrders) { if (k !== key) { @@ -130,8 +130,8 @@ // Reset to original data when 'none' and stop further sorting if (sortOrder === "none") { - originalTopTickers = [...topSectorTickers[selectedSector]]; // Reset originalTopTickers to sectorData - displayTopTickers = originalTopTickers; + originalPosTickers = [...topPosNetPremium]; // Reset originalPosTickers to sectorData + displayPosTickers = originalPosTickers?.slice(0, 50); return; } @@ -166,7 +166,66 @@ }; // Sort using the generic comparison function - displayTopTickers = [...originalTopTickers] + displayPosTickers = [...originalPosTickers] + .sort(compareValues) + ?.slice(0, 50); + }; + + const sortNegTickers = (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") { + originalNegTickers = [...topNegNetPremium]; + displayNegTickers = originalNegTickers?.slice(0, 50); + 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 + displayNegTickers = [...originalNegTickers] .sort(compareValues) ?.slice(0, 50); }; @@ -174,7 +233,9 @@ function getPlotOptions() { isLoading = true; let dates = marketTideData?.map((item) => item?.time); - const priceList = marketTideData?.map((item) => item?.close); + const priceList = marketTideData?.map((item) => + item?.close !== null ? item?.close?.toFixed(2) : item?.close, + ); const netCallPremList = marketTideData?.map( (item) => item?.net_call_premium, ); @@ -296,7 +357,7 @@ let [hours, minutes] = timePart.split(":").map(Number); // Only show labels at 30-minute intervals (XX:00 and XX:30) - if (minutes % 60 === 0) { + if (minutes % 30 === 0) { const amPm = hours >= 12 ? "PM" : "AM"; hours = hours % 12 || 12; return minutes === 0 @@ -305,7 +366,7 @@ } return ""; }, - interval: 29, // Show label every 30 minutes (29 intervals between) + interval: "auto", // Show label every 30 minutes (29 intervals between) }, }, @@ -426,18 +487,6 @@ return options; } optionsData = marketTideData ? getPlotOptions() : null; - - /* - $: { - if (selectedSector) { - originalTopTickers = [...topSectorTickers[selectedSector]]; - displayTopTickers = - data?.user?.tier === "Pro" - ? displayTopTickers - : displayTopTickers?.slice(0, 3); - } - } - */
@@ -580,15 +629,15 @@ - {#each displayTopTickers as item, index} + {#each displayPosTickers as item, index} -