add more rules to screener
This commit is contained in:
parent
7ef9794f8d
commit
a98588852e
@ -3,7 +3,16 @@ import { validateData } from "$lib/utils";
|
|||||||
import { loginUserSchema, registerUserSchema } from "$lib/schemas";
|
import { loginUserSchema, registerUserSchema } from "$lib/schemas";
|
||||||
|
|
||||||
// Define the EMA parameters to check
|
// Define the EMA parameters to check
|
||||||
const emaParameters = ["ema20", "ema50", "ema100", "ema200"];
|
const emaParameters = [
|
||||||
|
"sma20",
|
||||||
|
"sma50",
|
||||||
|
"sma100",
|
||||||
|
"sma200",
|
||||||
|
"ema20",
|
||||||
|
"ema50",
|
||||||
|
"ema100",
|
||||||
|
"ema200",
|
||||||
|
];
|
||||||
// Function to check and add missing EMA parameters
|
// Function to check and add missing EMA parameters
|
||||||
const ensureAllEmaParameters = (params) => {
|
const ensureAllEmaParameters = (params) => {
|
||||||
const includedEmaParameters = params.filter((param) =>
|
const includedEmaParameters = params.filter((param) =>
|
||||||
|
|||||||
@ -61,6 +61,7 @@ const allRules = {
|
|||||||
ema50: { label: 'EMA50', step: ['Stock Price > EMA50', 'EMA50 > EMA20', 'EMA50 > EMA100', 'EMA50 > EMA200'], category: 'ta', defaultValue: 'any' },
|
ema50: { label: 'EMA50', step: ['Stock Price > EMA50', 'EMA50 > EMA20', 'EMA50 > EMA100', 'EMA50 > EMA200'], category: 'ta', defaultValue: 'any' },
|
||||||
ema100: { label: 'EMA100', step: ['Stock Price > EMA100', 'EMA100 > EMA20', 'EMA100 > EMA50', 'EMA100 > EMA200'], category: 'ta', defaultValue: 'any' },
|
ema100: { label: 'EMA100', step: ['Stock Price > EMA100', 'EMA100 > EMA20', 'EMA100 > EMA50', 'EMA100 > EMA200'], category: 'ta', defaultValue: 'any' },
|
||||||
ema200: { label: 'EMA200', step: ['Stock Price > EMA200', 'EMA200 > EMA20', 'EMA200 > EMA50', 'EMA200 > EMA100'], category: 'ta', defaultValue: 'any' },
|
ema200: { label: 'EMA200', step: ['Stock Price > EMA200', 'EMA200 > EMA20', 'EMA200 > EMA50', 'EMA200 > EMA100'], category: 'ta', defaultValue: 'any' },
|
||||||
|
grahamNumber: { label: 'Graham Number', step: ['Price > Graham Number','Price < Graham Number'], defaultValue: 'any' },
|
||||||
price: { label: 'Stock Price', step: [1000,500,400,300,200,150,100,80,60,50,20,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: 10 },
|
price: { label: 'Stock Price', step: [1000,500,400,300,200,150,100,80,60,50,20,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: 10 },
|
||||||
|
|
||||||
change1W: { label: 'Price Change 1W', step: ['20%','10%','5%','1%','-1%','-5%','-10%','-20%'], category: 'ta', defaultCondition: 'over', defaultValue: '1%' },
|
change1W: { label: 'Price Change 1W', step: ['20%','10%','5%','1%','-1%','-5%','-10%','-20%'], category: 'ta', defaultCondition: 'over', defaultValue: '1%' },
|
||||||
@ -72,6 +73,7 @@ const allRules = {
|
|||||||
marketCap: { label: 'Market Cap', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
marketCap: { label: 'Market Cap', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
||||||
workingCapital: { label: 'Working Capital', step: ['20B','10B','5B','1B','500M','100M','50M','10M','1M','0'], category: 'fund', defaultCondition: 'over', defaultValue: 'any' },
|
workingCapital: { label: 'Working Capital', step: ['20B','10B','5B','1B','500M','100M','50M','10M','1M','0'], category: 'fund', defaultCondition: 'over', defaultValue: 'any' },
|
||||||
totalAssets: { label: 'Total Assets', step: ['500B','200B','100B','50B','10B','1B','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: 'any' },
|
totalAssets: { label: 'Total Assets', step: ['500B','200B','100B','50B','10B','1B','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: 'any' },
|
||||||
|
tangibleAssetValue: { label: 'Tangible Assets', step: ['500B','200B','100B','50B','10B','1B','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: 'any' },
|
||||||
revenue: { label: 'Revenue', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
revenue: { label: 'Revenue', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
||||||
growthRevenue: { label: 'Revenue Growth', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
|
growthRevenue: { label: 'Revenue Growth', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
|
||||||
costOfRevenue: { label: 'Cost of Revenue', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
costOfRevenue: { label: 'Cost of Revenue', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
||||||
@ -131,6 +133,7 @@ const allRules = {
|
|||||||
debtRatio: { label: 'Debt Ratio', step: [1,0.5,0,-0.5,-1], category: 'fund', defaultCondition: 'over', defaultValue: -0.5 },
|
debtRatio: { label: 'Debt Ratio', step: [1,0.5,0,-0.5,-1], category: 'fund', defaultCondition: 'over', defaultValue: -0.5 },
|
||||||
returnOnAssets: { label: 'Return on Assets', step: [10,8,6,4,2,1,0,-2,-4,-6,-8,-10], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
returnOnAssets: { label: 'Return on Assets', step: [10,8,6,4,2,1,0,-2,-4,-6,-8,-10], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
||||||
returnOnEquity: { label: 'Return on Equity', step: [10,8,6,4,2,1,0,-2,-4,-6,-8,-10], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
returnOnEquity: { label: 'Return on Equity', step: [10,8,6,4,2,1,0,-2,-4,-6,-8,-10], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
||||||
|
returnOnTangibleAssets: { label: 'Return on Tangible Assets', step: [10,8,6,4,2,1,0,-2,-4,-6,-8,-10], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
||||||
enterpriseValue: { label: 'Enterprise Value', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
enterpriseValue: { label: 'Enterprise Value', step: ['100B','50B','10B','1B','300M','100M','10M'], category: 'fund', defaultCondition: 'over', defaultValue: '10M' },
|
||||||
freeCashFlowPerShare: { label: 'FCF / Share', step: [10,8,6,4,2,1,0], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
freeCashFlowPerShare: { label: 'FCF / Share', step: [10,8,6,4,2,1,0], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
||||||
cashPerShare: { label: 'Cash / Share', step: [50,20,10,5,1,0,-1,-5,-10,-20,-50], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
cashPerShare: { label: 'Cash / Share', step: [50,20,10,5,1,0,-1,-5,-10,-20,-50], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
||||||
@ -145,6 +148,12 @@ const allRules = {
|
|||||||
freeCashFlow: { label: 'Free Cash Flow', step: ['50B','10B','1B','100M','10M','1M',0], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
freeCashFlow: { label: 'Free Cash Flow', step: ['50B','10B','1B','100M','10M','1M',0], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
||||||
operatingCashFlow: { label: 'Operating Cash Flow', step: ['50B','10B','1B','100M','10M','1M',0], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
operatingCashFlow: { label: 'Operating Cash Flow', step: ['50B','10B','1B','100M','10M','1M',0], category: 'fund', defaultCondition: 'over', defaultValue: '0' },
|
||||||
operatingCashFlowPerShare: { label: 'Operating Cash Flow / Share', step: [50,40,30,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
operatingCashFlowPerShare: { label: 'Operating Cash Flow / Share', step: [50,40,30,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
||||||
|
revenuePerShare: { label: 'Revenue / Share', step: [50,40,30,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
||||||
|
netIncomePerShare: { label: 'Net Income / Share', step: [50,40,30,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
||||||
|
shareholdersEquityPerShare: { label: 'Shareholders Equity / Share', step: [50,40,30,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
||||||
|
interestDebtPerShare: { label: 'Interest Debt / Share', step: [50,40,30,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
||||||
|
capexPerShare: { label: 'CapEx / Share', step: [50,40,30,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
||||||
|
|
||||||
freeCashFlowMargin: { label: 'FCF Margin', step: ['80%','50%','20%','10%','5%','0%','-5%','-10%','-20%','-50%'], category: 'fund', defaultCondition: 'over', defaultValue: '0%' },
|
freeCashFlowMargin: { label: 'FCF Margin', step: ['80%','50%','20%','10%','5%','0%','-5%','-10%','-20%','-50%'], category: 'fund', defaultCondition: 'over', defaultValue: '0%' },
|
||||||
totalDebt: { label: 'Total Debt', step: ['200B','100B','50B','10B','1B','100M','10M','1M'], category: 'fund', defaultCondition: 'over', defaultValue: '1M' },
|
totalDebt: { label: 'Total Debt', step: ['200B','100B','50B','10B','1B','100M','10M','1M'], category: 'fund', defaultCondition: 'over', defaultValue: '1M' },
|
||||||
cashFlowToDebtRatio: { label: 'Cash Flow / Debt', step: [50,40,30,20,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
cashFlowToDebtRatio: { label: 'Cash Flow / Debt', step: [50,40,30,20,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: '1' },
|
||||||
@ -432,6 +441,7 @@ function handleAddRule() {
|
|||||||
case 'ema100':
|
case 'ema100':
|
||||||
case 'ema200':
|
case 'ema200':
|
||||||
case 'sma20':
|
case 'sma20':
|
||||||
|
case 'grahamNumber':
|
||||||
case 'sma50':
|
case 'sma50':
|
||||||
case 'sma100':
|
case 'sma100':
|
||||||
case 'sma200':
|
case 'sma200':
|
||||||
@ -714,8 +724,7 @@ async function handleChangeValue(value) {
|
|||||||
checkedItems.set(ruleName, new Set([value]));
|
checkedItems.set(ruleName, new Set([value]));
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(checkedItems)
|
if (['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200','grahamNumber','analystRating','score','sector','industry','country']?.includes(ruleName)) {
|
||||||
if (['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200','analystRating','score','sector','industry','country']?.includes(ruleName)) {
|
|
||||||
// Ensure valueMappings[ruleName] is initialized as an array
|
// Ensure valueMappings[ruleName] is initialized as an array
|
||||||
searchQuery = '';
|
searchQuery = '';
|
||||||
if (!Array.isArray(valueMappings[ruleName])) {
|
if (!Array.isArray(valueMappings[ruleName])) {
|
||||||
@ -1126,7 +1135,7 @@ function handleInput(event) {
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Content class="w-56 h-fit max-h-72 overflow-y-auto scroller">
|
<DropdownMenu.Content class="w-56 h-fit max-h-72 overflow-y-auto scroller">
|
||||||
{#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'analystRating','score','sector','industry','country']?.includes(row?.rule)}
|
{#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'grahamNumber','analystRating','score','sector','industry','country']?.includes(row?.rule)}
|
||||||
<DropdownMenu.Label class="absolute mt-2 h-11 border-gray-800 border-b -top-1 z-20 fixed sticky bg-[#09090B]">
|
<DropdownMenu.Label class="absolute mt-2 h-11 border-gray-800 border-b -top-1 z-20 fixed sticky bg-[#09090B]">
|
||||||
<div class="flex items-center justify-start gap-x-1">
|
<div class="flex items-center justify-start gap-x-1">
|
||||||
<div class="relative inline-block flex flex-row items-center justify-center">
|
<div class="relative inline-block flex flex-row items-center justify-center">
|
||||||
@ -1156,7 +1165,7 @@ function handleInput(event) {
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<DropdownMenu.Group class="min-h-10 mt-2">
|
<DropdownMenu.Group class="min-h-10 mt-2">
|
||||||
{#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'analystRating','score','sector','industry','country']?.includes(row?.rule)}
|
{#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'grahamNumber','analystRating','score','sector','industry','country']?.includes(row?.rule)}
|
||||||
{#each row?.step as newValue}
|
{#each row?.step as newValue}
|
||||||
<DropdownMenu.Item class="sm:hover:bg-[#27272A]">
|
<DropdownMenu.Item class="sm:hover:bg-[#27272A]">
|
||||||
|
|
||||||
@ -1165,7 +1174,7 @@ function handleInput(event) {
|
|||||||
</button>
|
</button>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
{/each}
|
{/each}
|
||||||
{:else if ['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200']?.includes(row?.rule)}
|
{:else if ['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200','grahamNumber']?.includes(row?.rule)}
|
||||||
{#each row?.step as item}
|
{#each row?.step as item}
|
||||||
<DropdownMenu.Item class="sm:hover:bg-[#27272A]">
|
<DropdownMenu.Item class="sm:hover:bg-[#27272A]">
|
||||||
<div class="flex items-center" on:click|capture={(event) => event.preventDefault()}>
|
<div class="flex items-center" on:click|capture={(event) => event.preventDefault()}>
|
||||||
@ -1353,11 +1362,7 @@ function handleInput(event) {
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]">
|
<td class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]">
|
||||||
{#if item?.symbol?.includes('.DE') || item?.symbol?.includes('.F')}
|
{item?.marketCap < 100 ? '< 100' : abbreviateNumber(item?.marketCap)}
|
||||||
€{item?.marketCap < 100 ? '< $100' : abbreviateNumber(item?.marketCap)}
|
|
||||||
{:else}
|
|
||||||
{item?.marketCap < 100 ? '< $100' : abbreviateNumber(item?.marketCap,true)}
|
|
||||||
{/if}
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="text-white text-end text-sm sm:text-[1rem] font-medium border-b-[#09090B]">
|
<td class="text-white text-end text-sm sm:text-[1rem] font-medium border-b-[#09090B]">
|
||||||
@ -1369,7 +1374,7 @@ function handleInput(event) {
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]">
|
<td class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]">
|
||||||
{item?.price < 0.01 ? '< $0.01' : item?.price?.toFixed(2)}
|
{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]">
|
<td class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]">
|
||||||
@ -1414,7 +1419,7 @@ function handleInput(event) {
|
|||||||
{item?.name?.length > charNumber ? item?.name?.slice(0, charNumber) + "..." : item?.name}
|
{item?.name?.length > charNumber ? item?.name?.slice(0, charNumber) + "..." : item?.name}
|
||||||
</td>
|
</td>
|
||||||
<td class="whitespace-nowrap text-sm sm:text-[1rem] text-end text-white border-b-[#09090B]">
|
<td class="whitespace-nowrap text-sm sm:text-[1rem] text-end text-white border-b-[#09090B]">
|
||||||
{abbreviateNumber(item?.marketCap, true)}
|
{abbreviateNumber(item?.marketCap)}
|
||||||
</td>
|
</td>
|
||||||
{#each displayRules as row (row?.rule)}
|
{#each displayRules as row (row?.rule)}
|
||||||
{#if row?.rule !== 'marketCap'}
|
{#if row?.rule !== 'marketCap'}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Cache to store previous requests
|
// Cache to store previous requests
|
||||||
let cache = new Map();
|
let cache = new Map();
|
||||||
|
|
||||||
const getStockScreenerData = async (rules, apiKey, apiURL) => {
|
const getStockScreenerData = async (rules) => {
|
||||||
console.log("Checking cache and fetching new data if needed");
|
console.log("Checking cache and fetching new data if needed");
|
||||||
|
|
||||||
// Extract the rule names
|
// Extract the rule names
|
||||||
|
|||||||
@ -37,6 +37,9 @@ const movingAverageConditions = {
|
|||||||
"SMA200 > SMA50": (item) => item.sma200 > item.sma50,
|
"SMA200 > SMA50": (item) => item.sma200 > item.sma50,
|
||||||
"SMA200 > SMA100": (item) => item.sma200 > item.sma100,
|
"SMA200 > SMA100": (item) => item.sma200 > item.sma100,
|
||||||
// Add additional SMA conditions here
|
// Add additional SMA conditions here
|
||||||
|
|
||||||
|
"Price > Graham Number": (item) => item.price > item.grahamNumber,
|
||||||
|
"Price < Graham Number": (item) => item.price < item.grahamNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert the input to a value or return it as-is if it's already an array
|
// Convert the input to a value or return it as-is if it's already an array
|
||||||
@ -130,6 +133,7 @@ async function filterStockScreenerData(stockScreenerData, ruleOfList) {
|
|||||||
"sma50",
|
"sma50",
|
||||||
"sma100",
|
"sma100",
|
||||||
"sma200",
|
"sma200",
|
||||||
|
"grahamnumber", //grahamNumber into lowerCase form
|
||||||
].includes(ruleName)
|
].includes(ruleName)
|
||||||
) {
|
) {
|
||||||
if (ruleValue === "any") return true;
|
if (ruleValue === "any") return true;
|
||||||
@ -138,7 +142,7 @@ async function filterStockScreenerData(stockScreenerData, ruleOfList) {
|
|||||||
if (movingAverageConditions[condition]) {
|
if (movingAverageConditions[condition]) {
|
||||||
if (!movingAverageConditions[condition](item)) return false;
|
if (!movingAverageConditions[condition](item)) return false;
|
||||||
} else {
|
} else {
|
||||||
console.warn(`Unknown condition: ${condition}`);
|
//console.warn(`Unknown condition: ${condition}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user