add performance tab
This commit is contained in:
parent
37996119b1
commit
582cb04e49
@ -47,6 +47,7 @@
|
|||||||
let displayRules = [];
|
let displayRules = [];
|
||||||
let selectedPopularStrategy = "";
|
let selectedPopularStrategy = "";
|
||||||
let displayTableTab = "general";
|
let displayTableTab = "general";
|
||||||
|
let otherTabRules = [];
|
||||||
|
|
||||||
let stockScreenerData = data?.getStockScreenerData?.filter((item) =>
|
let stockScreenerData = data?.getStockScreenerData?.filter((item) =>
|
||||||
Object?.values(item)?.every(
|
Object?.values(item)?.every(
|
||||||
@ -217,7 +218,7 @@
|
|||||||
step: ["20%", "10%", "5%", "1%", "-1%", "-5%", "-10%", "-20%"],
|
step: ["20%", "10%", "5%", "1%", "-1%", "-5%", "-10%", "-20%"],
|
||||||
category: "ta",
|
category: "ta",
|
||||||
defaultCondition: "over",
|
defaultCondition: "over",
|
||||||
defaultValue: "1%",
|
defaultValue: "any",
|
||||||
},
|
},
|
||||||
change1M: {
|
change1M: {
|
||||||
label: "Price Change 1M",
|
label: "Price Change 1M",
|
||||||
@ -236,7 +237,7 @@
|
|||||||
],
|
],
|
||||||
category: "ta",
|
category: "ta",
|
||||||
defaultCondition: "over",
|
defaultCondition: "over",
|
||||||
defaultValue: "10%",
|
defaultValue: "any",
|
||||||
},
|
},
|
||||||
change3M: {
|
change3M: {
|
||||||
label: "Price Change 3M",
|
label: "Price Change 3M",
|
||||||
@ -255,7 +256,7 @@
|
|||||||
],
|
],
|
||||||
category: "ta",
|
category: "ta",
|
||||||
defaultCondition: "over",
|
defaultCondition: "over",
|
||||||
defaultValue: "10%",
|
defaultValue: "any",
|
||||||
},
|
},
|
||||||
change6M: {
|
change6M: {
|
||||||
label: "Price Change 6M",
|
label: "Price Change 6M",
|
||||||
@ -274,7 +275,7 @@
|
|||||||
],
|
],
|
||||||
category: "ta",
|
category: "ta",
|
||||||
defaultCondition: "over",
|
defaultCondition: "over",
|
||||||
defaultValue: "10%",
|
defaultValue: "any",
|
||||||
},
|
},
|
||||||
change1Y: {
|
change1Y: {
|
||||||
label: "Price Change 1Y",
|
label: "Price Change 1Y",
|
||||||
@ -293,7 +294,7 @@
|
|||||||
],
|
],
|
||||||
category: "ta",
|
category: "ta",
|
||||||
defaultCondition: "over",
|
defaultCondition: "over",
|
||||||
defaultValue: "10%",
|
defaultValue: "any",
|
||||||
},
|
},
|
||||||
change3Y: {
|
change3Y: {
|
||||||
label: "Price Change 3Y",
|
label: "Price Change 3Y",
|
||||||
@ -312,7 +313,7 @@
|
|||||||
],
|
],
|
||||||
category: "ta",
|
category: "ta",
|
||||||
defaultCondition: "over",
|
defaultCondition: "over",
|
||||||
defaultValue: "10%",
|
defaultValue: "any",
|
||||||
},
|
},
|
||||||
marketCap: {
|
marketCap: {
|
||||||
label: "Market Cap",
|
label: "Market Cap",
|
||||||
@ -1478,8 +1479,9 @@
|
|||||||
|
|
||||||
const handleMessage = (event) => {
|
const handleMessage = (event) => {
|
||||||
displayRules = allRows?.filter((row) =>
|
displayRules = allRows?.filter((row) =>
|
||||||
ruleOfList.some((rule) => rule.name === row.rule),
|
ruleOfList?.some((rule) => rule.name === row.rule),
|
||||||
);
|
);
|
||||||
|
|
||||||
filteredData = event.data?.filteredData ?? [];
|
filteredData = event.data?.filteredData ?? [];
|
||||||
displayResults = filteredData?.slice(0, 50);
|
displayResults = filteredData?.slice(0, 50);
|
||||||
};
|
};
|
||||||
@ -1490,11 +1492,27 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loadWorker = async () => {
|
const loadWorker = async () => {
|
||||||
syncWorker.postMessage({ stockScreenerData, ruleOfList });
|
if (displayTableTab === "performance") {
|
||||||
|
syncWorker.postMessage({
|
||||||
|
stockScreenerData,
|
||||||
|
ruleOfList: [...ruleOfList, ...otherTabRules],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
syncWorker.postMessage({
|
||||||
|
stockScreenerData,
|
||||||
|
ruleOfList,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateStockScreenerData = async () => {
|
const updateStockScreenerData = async () => {
|
||||||
downloadWorker.postMessage({ ruleOfList: ruleOfList });
|
if (displayTableTab === "performance") {
|
||||||
|
downloadWorker.postMessage({
|
||||||
|
ruleOfList: [...ruleOfList, ...otherTabRules],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
downloadWorker.postMessage({ ruleOfList: ruleOfList });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleAddRule() {
|
function handleAddRule() {
|
||||||
@ -1988,8 +2006,8 @@ const handleKeyDown = (event) => {
|
|||||||
{ key: "symbol", label: "Symbol", align: "left" },
|
{ key: "symbol", label: "Symbol", align: "left" },
|
||||||
{ key: "name", label: "Name", align: "left" },
|
{ key: "name", label: "Name", align: "left" },
|
||||||
{ key: "marketCap", label: "Market Cap", align: "right" },
|
{ key: "marketCap", label: "Market Cap", align: "right" },
|
||||||
{ key: "changesPercentage", label: "% Change", align: "right" },
|
|
||||||
{ key: "price", label: "Price", align: "right" },
|
{ key: "price", label: "Price", align: "right" },
|
||||||
|
{ key: "changesPercentage", label: "% Change", align: "right" },
|
||||||
{ key: "volume", label: "Volume", align: "right" },
|
{ key: "volume", label: "Volume", align: "right" },
|
||||||
{ key: "pe", label: "PE Ratio", align: "right" },
|
{ key: "pe", label: "PE Ratio", align: "right" },
|
||||||
];
|
];
|
||||||
@ -2004,19 +2022,6 @@ const handleKeyDown = (event) => {
|
|||||||
pe: { order: "none", type: "number" },
|
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 = [
|
const stringTypeRules = [
|
||||||
"country",
|
"country",
|
||||||
"industry",
|
"industry",
|
||||||
@ -2032,18 +2037,43 @@ const handleKeyDown = (event) => {
|
|||||||
|
|
||||||
$: {
|
$: {
|
||||||
if (displayTableTab) {
|
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") {
|
if (displayTableTab === "general") {
|
||||||
// Set columns and sortOrders for the "general" tab
|
|
||||||
columns = [...generalColumns];
|
columns = [...generalColumns];
|
||||||
sortOrders = { ...generalSortOrders };
|
sortOrders = { ...generalSortOrders };
|
||||||
} else {
|
} else {
|
||||||
// Set base columns and sortOrders, then extend with displayRules
|
columns = [...(baseColumnsMap[displayTableTab] || [])];
|
||||||
columns = [...baseColumns];
|
sortOrders = { ...(baseSortOrdersMap[displayTableTab] || {}) };
|
||||||
sortOrders = { ...baseSortOrders };
|
|
||||||
|
|
||||||
displayRules?.forEach((rule) => {
|
const rulesList =
|
||||||
|
displayTableTab === "performance" ? tabRuleList : displayRules;
|
||||||
|
rulesList?.forEach((rule) => {
|
||||||
if (rule.rule !== "marketCap") {
|
if (rule.rule !== "marketCap") {
|
||||||
// Ignore "marketCap" if it's present in displayRules
|
|
||||||
columns.push({
|
columns.push({
|
||||||
key: rule.rule,
|
key: rule.rule,
|
||||||
label: rule.label,
|
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>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -2757,9 +2807,9 @@ const handleKeyDown = (event) => {
|
|||||||
{filteredData?.length} Stocks
|
{filteredData?.length} Stocks
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<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
|
<ul
|
||||||
class="flex flex-row items-center space-x-2 whitespace-nowrap text-base"
|
class="flex flex-row items-center space-x-2 whitespace-nowrap text-base"
|
||||||
>
|
>
|
||||||
@ -2794,8 +2844,19 @@ const handleKeyDown = (event) => {
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</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>
|
</ul>
|
||||||
<div class="w-fit ml-auto">
|
<div class="w-fit ml-auto hidden sm:inline-block">
|
||||||
<DownloadData
|
<DownloadData
|
||||||
{data}
|
{data}
|
||||||
rawData={filteredData}
|
rawData={filteredData}
|
||||||
@ -2847,6 +2908,12 @@ const handleKeyDown = (event) => {
|
|||||||
: abbreviateNumber(item?.marketCap)}
|
: abbreviateNumber(item?.marketCap)}
|
||||||
</td>
|
</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
|
<td
|
||||||
class="text-white text-end text-sm sm:text-[1rem] font-medium border-b-[#09090B]"
|
class="text-white text-end text-sm sm:text-[1rem] font-medium border-b-[#09090B]"
|
||||||
>
|
>
|
||||||
@ -2865,12 +2932,6 @@ const handleKeyDown = (event) => {
|
|||||||
{/if}
|
{/if}
|
||||||
</td>
|
</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
|
<td
|
||||||
class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]"
|
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)}
|
{#if ["ema20", "ema50", "ema100", "ema200", "analystRating", "halalStocks", "score", "sector", "industry", "country"]?.includes(row?.rule)}
|
||||||
{item[row?.rule]}
|
{item[row?.rule]}
|
||||||
{:else if ["fundamentalAnalysis", "trendAnalysis"]?.includes(row?.rule)}
|
|
||||||
{item[row?.rule]?.accuracy}%
|
|
||||||
{:else}
|
{:else}
|
||||||
{abbreviateNumber(item[row?.rule])}
|
{abbreviateNumber(item[row?.rule])}
|
||||||
{/if}
|
{/if}
|
||||||
@ -2942,6 +3001,65 @@ const handleKeyDown = (event) => {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</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}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -65,7 +65,6 @@ const getStockScreenerData = async (rules) => {
|
|||||||
|
|
||||||
onmessage = async (event) => {
|
onmessage = async (event) => {
|
||||||
const { ruleOfList } = event.data || {};
|
const { ruleOfList } = event.data || {};
|
||||||
|
|
||||||
const output = await getStockScreenerData(ruleOfList);
|
const output = await getStockScreenerData(ruleOfList);
|
||||||
|
|
||||||
const stockScreenerData = output?.filter((item) =>
|
const stockScreenerData = output?.filter((item) =>
|
||||||
@ -79,7 +78,6 @@ onmessage = async (event) => {
|
|||||||
))
|
))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
postMessage({ message: "success", stockScreenerData });
|
postMessage({ message: "success", stockScreenerData });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user