add performance tab

This commit is contained in:
MuslemRahimi 2024-11-19 17:41:50 +01:00
parent 37996119b1
commit 582cb04e49
2 changed files with 158 additions and 42 deletions

View File

@ -47,6 +47,7 @@
let displayRules = [];
let selectedPopularStrategy = "";
let displayTableTab = "general";
let otherTabRules = [];
let stockScreenerData = data?.getStockScreenerData?.filter((item) =>
Object?.values(item)?.every(
@ -217,7 +218,7 @@
step: ["20%", "10%", "5%", "1%", "-1%", "-5%", "-10%", "-20%"],
category: "ta",
defaultCondition: "over",
defaultValue: "1%",
defaultValue: "any",
},
change1M: {
label: "Price Change 1M",
@ -236,7 +237,7 @@
],
category: "ta",
defaultCondition: "over",
defaultValue: "10%",
defaultValue: "any",
},
change3M: {
label: "Price Change 3M",
@ -255,7 +256,7 @@
],
category: "ta",
defaultCondition: "over",
defaultValue: "10%",
defaultValue: "any",
},
change6M: {
label: "Price Change 6M",
@ -274,7 +275,7 @@
],
category: "ta",
defaultCondition: "over",
defaultValue: "10%",
defaultValue: "any",
},
change1Y: {
label: "Price Change 1Y",
@ -293,7 +294,7 @@
],
category: "ta",
defaultCondition: "over",
defaultValue: "10%",
defaultValue: "any",
},
change3Y: {
label: "Price Change 3Y",
@ -312,7 +313,7 @@
],
category: "ta",
defaultCondition: "over",
defaultValue: "10%",
defaultValue: "any",
},
marketCap: {
label: "Market Cap",
@ -1478,8 +1479,9 @@
const handleMessage = (event) => {
displayRules = allRows?.filter((row) =>
ruleOfList.some((rule) => rule.name === row.rule),
ruleOfList?.some((rule) => rule.name === row.rule),
);
filteredData = event.data?.filteredData ?? [];
displayResults = filteredData?.slice(0, 50);
};
@ -1490,11 +1492,27 @@
};
const loadWorker = async () => {
syncWorker.postMessage({ stockScreenerData, ruleOfList });
if (displayTableTab === "performance") {
syncWorker.postMessage({
stockScreenerData,
ruleOfList: [...ruleOfList, ...otherTabRules],
});
} else {
syncWorker.postMessage({
stockScreenerData,
ruleOfList,
});
}
};
const updateStockScreenerData = async () => {
downloadWorker.postMessage({ ruleOfList: ruleOfList });
if (displayTableTab === "performance") {
downloadWorker.postMessage({
ruleOfList: [...ruleOfList, ...otherTabRules],
});
} else {
downloadWorker.postMessage({ ruleOfList: ruleOfList });
}
};
function handleAddRule() {
@ -1988,8 +2006,8 @@ const handleKeyDown = (event) => {
{ key: "symbol", label: "Symbol", align: "left" },
{ key: "name", label: "Name", align: "left" },
{ key: "marketCap", label: "Market Cap", align: "right" },
{ key: "changesPercentage", label: "% Change", align: "right" },
{ key: "price", label: "Price", align: "right" },
{ key: "changesPercentage", label: "% Change", align: "right" },
{ key: "volume", label: "Volume", align: "right" },
{ key: "pe", label: "PE Ratio", align: "right" },
];
@ -2004,19 +2022,6 @@ const handleKeyDown = (event) => {
pe: { order: "none", type: "number" },
};
// Initial columns and sort orders for other tabs
const baseColumns = [
{ key: "symbol", label: "Symbol", align: "left" },
{ key: "name", label: "Name", align: "left" },
{ key: "marketCap", label: "Market Cap", align: "right" },
];
const baseSortOrders = {
symbol: { order: "none", type: "string" },
name: { order: "none", type: "string" },
marketCap: { order: "none", type: "number" },
};
const stringTypeRules = [
"country",
"industry",
@ -2032,18 +2037,43 @@ const handleKeyDown = (event) => {
$: {
if (displayTableTab) {
const baseColumnsMap = {
performance: [
{ key: "symbol", label: "Symbol", align: "left" },
{ key: "name", label: "Name", align: "left" },
{ key: "marketCap", label: "Market Cap", align: "right" },
],
filters: [
{ key: "symbol", label: "Symbol", align: "left" },
{ key: "name", label: "Name", align: "left" },
{ key: "marketCap", label: "Market Cap", align: "right" },
],
};
const baseSortOrdersMap = {
performance: {
symbol: { order: "none", type: "string" },
name: { order: "none", type: "string" },
marketCap: { order: "none", type: "number" },
},
filters: {
symbol: { order: "none", type: "string" },
name: { order: "none", type: "string" },
marketCap: { order: "none", type: "number" },
},
};
if (displayTableTab === "general") {
// Set columns and sortOrders for the "general" tab
columns = [...generalColumns];
sortOrders = { ...generalSortOrders };
} else {
// Set base columns and sortOrders, then extend with displayRules
columns = [...baseColumns];
sortOrders = { ...baseSortOrders };
columns = [...(baseColumnsMap[displayTableTab] || [])];
sortOrders = { ...(baseSortOrdersMap[displayTableTab] || {}) };
displayRules?.forEach((rule) => {
const rulesList =
displayTableTab === "performance" ? tabRuleList : displayRules;
rulesList?.forEach((rule) => {
if (rule.rule !== "marketCap") {
// Ignore "marketCap" if it's present in displayRules
columns.push({
key: rule.rule,
label: rule.label,
@ -2055,6 +2085,26 @@ const handleKeyDown = (event) => {
}
}
}
let tabRuleList = [];
async function changeTab(state) {
displayTableTab = state;
if (displayTableTab === "performance") {
otherTabRules = [
{ name: "marketCap", value: "any" },
{ name: "change1W", value: "any" },
{ name: "change1M", value: "any" },
{ name: "change3M", value: "any" },
{ name: "change1Y", value: "any" },
];
tabRuleList = otherTabRules
.map((rule) => allRows.find((row) => row.rule === rule.name))
.filter(Boolean);
await updateStockScreenerData();
}
}
</script>
<svelte:head>
@ -2757,9 +2807,9 @@ const handleKeyDown = (event) => {
{filteredData?.length} Stocks
</h2>
<div
class="hide-scroll col-span-2 flex flex-row items-center border-t border-gray-600 lg:order-2 lg:grow lg:border-0 lg:pl-1 xl:pl-3"
class="col-span-2 flex flex-row items-center border-t border-gray-600 lg:order-2 lg:grow lg:border-0 lg:pl-1 xl:pl-3"
>
<nav class="grow flex flex-row items-center py-2.5 sm:py-3 lg:py-1">
<nav class="w-full flex flex-row items-center py-2.5 sm:py-3 lg:py-1">
<ul
class="flex flex-row items-center space-x-2 whitespace-nowrap text-base"
>
@ -2794,8 +2844,19 @@ const handleKeyDown = (event) => {
</span>
</button>
</li>
<li>
<button
on:click={() => changeTab("performance")}
class="text-[1rem] sm:text-lg block text-white rounded-md px-2 py-1 focus:outline-none sm:hover:bg-[#27272A] {displayTableTab ===
'performance'
? 'font-semibold bg-[#27272A]'
: ''}"
>
Performance
</button>
</li>
</ul>
<div class="w-fit ml-auto">
<div class="w-fit ml-auto hidden sm:inline-block">
<DownloadData
{data}
rawData={filteredData}
@ -2847,6 +2908,12 @@ const handleKeyDown = (event) => {
: abbreviateNumber(item?.marketCap)}
</td>
<td
class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]"
>
{item?.price < 0.01 ? "< 0.01" : item?.price?.toFixed(2)}
</td>
<td
class="text-white text-end text-sm sm:text-[1rem] font-medium border-b-[#09090B]"
>
@ -2865,12 +2932,6 @@ const handleKeyDown = (event) => {
{/if}
</td>
<td
class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]"
>
{item?.price < 0.01 ? "< 0.01" : item?.price?.toFixed(2)}
</td>
<td
class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]"
>
@ -2929,8 +2990,6 @@ const handleKeyDown = (event) => {
>
{#if ["ema20", "ema50", "ema100", "ema200", "analystRating", "halalStocks", "score", "sector", "industry", "country"]?.includes(row?.rule)}
{item[row?.rule]}
{:else if ["fundamentalAnalysis", "trendAnalysis"]?.includes(row?.rule)}
{item[row?.rule]?.accuracy}%
{:else}
{abbreviateNumber(item[row?.rule])}
{/if}
@ -2942,6 +3001,65 @@ const handleKeyDown = (event) => {
</tbody>
</table>
</div>
{:else if displayTableTab === "performance"}
<div class="w-full rounded-md overflow-x-scroll">
<table
class="table table-sm table-compact w-full bg-[#09090B] border-bg-[#09090B]"
>
<thead>
<TableHeader {columns} {sortOrders} {sortData} />
</thead>
<tbody>
{#each displayResults as item (item?.symbol)}
<tr
on:click={() => {
handleSave(false);
}}
class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] bg-[#09090B] border-b-[#09090B] odd:bg-[#27272A]"
>
<td class="border-b-[#09090B] whitespace-nowrap">
<a
href={"/stocks/" + item?.symbol}
class="sm:hover:text-white text-blue-400 text-sm sm:text-[1rem]"
>{item?.symbol}</a
>
</td>
<td
class="whitespace-nowrap text-[1rem] text-white border-b-[#09090B]"
>
{item?.name?.length > charNumber
? item?.name?.slice(0, charNumber) + "..."
: item?.name}
</td>
{#each tabRuleList as row (row?.rule)}
<td
class="whitespace-nowrap text-sm sm:text-[1rem] text-end text-white border-b-[#09090B]"
>
{#if row?.rule === "marketCap"}
{abbreviateNumber(item[row?.rule])}
{:else if item[row?.rule] > 0}
<span class="text-[#00FC50]"
>+{abbreviateNumber(
item[row?.rule]?.toFixed(2),
)}%</span
>
{:else if item[row?.rule] < 0}
<span class="text-[#FF2F1F]"
>{abbreviateNumber(
item[row?.rule]?.toFixed(2),
)}%</span
>
{:else}
<span class="text-[#fff]">-</span>
{/if}
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
{:else}
<div

View File

@ -65,7 +65,6 @@ const getStockScreenerData = async (rules) => {
onmessage = async (event) => {
const { ruleOfList } = event.data || {};
const output = await getStockScreenerData(ruleOfList);
const stockScreenerData = output?.filter((item) =>
@ -79,7 +78,6 @@ onmessage = async (event) => {
))
)
);
postMessage({ message: "success", stockScreenerData });
};