diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index a2383b2f..ed50f02a 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1045,3 +1045,165 @@ export const sectorList = [
"Technology",
"Utilities",
];
+
+export const industryList = [
+ "Steel",
+ "Silver",
+ "Other Precious Metals",
+ "Gold",
+ "Copper",
+ "Aluminum",
+ "Paper, Lumber & Forest Products",
+ "Industrial Materials",
+ "Construction Materials",
+ "Chemicals - Specialty",
+ "Chemicals",
+ "Agricultural Inputs",
+ "Telecommunications Services",
+ "Internet Content & Information",
+ "Publishing",
+ "Broadcasting",
+ "Advertising Agencies",
+ "Entertainment",
+ "Travel Lodging",
+ "Travel Services",
+ "Specialty Retail",
+ "Luxury Goods",
+ "Home Improvement",
+ "Residential Construction",
+ "Department Stores",
+ "Personal Products & Services",
+ "Leisure",
+ "Gambling, Resorts & Casinos",
+ "Furnishings, Fixtures & Appliances",
+ "Restaurants",
+ "Auto - Parts",
+ "Auto - Manufacturers",
+ "Auto - Recreational Vehicles",
+ "Auto - Dealerships",
+ "Apparel - Retail",
+ "Apparel - Manufacturers",
+ "Apparel - Footwear & Accessories",
+ "Packaging & Containers",
+ "Tobacco",
+ "Grocery Stores",
+ "Discount Stores",
+ "Household & Personal Products",
+ "Packaged Foods",
+ "Food Distribution",
+ "Food Confectioners",
+ "Agricultural Farm Products",
+ "Education & Training Services",
+ "Beverages - Wineries & Distilleries",
+ "Beverages - Non-Alcoholic",
+ "Beverages - Alcoholic",
+ "Uranium",
+ "Solar",
+ "Oil & Gas Refining & Marketing",
+ "Oil & Gas Midstream",
+ "Oil & Gas Integrated",
+ "Oil & Gas Exploration & Production",
+ "Oil & Gas Equipment & Services",
+ "Oil & Gas Energy",
+ "Oil & Gas Drilling",
+ "Coal",
+ "Shell Companies",
+ "Investment - Banking & Investment Services",
+ "Insurance - Specialty",
+ "Insurance - Reinsurance",
+ "Insurance - Property & Casualty",
+ "Insurance - Life",
+ "Insurance - Diversified",
+ "Insurance - Brokers",
+ "Financial - Mortgages",
+ "Financial - Diversified",
+ "Financial - Data & Stock Exchanges",
+ "Financial - Credit Services",
+ "Financial - Conglomerates",
+ "Financial - Capital Markets",
+ "Banks - Regional",
+ "Banks - Diversified",
+ "Banks",
+ "Asset Management",
+ "Asset Management - Bonds",
+ "Asset Management - Income",
+ "Asset Management - Leveraged",
+ "Asset Management - Cryptocurrency",
+ "Asset Management - Global",
+ "Medical - Specialties",
+ "Medical - Pharmaceuticals",
+ "Medical - Instruments & Supplies",
+ "Medical - Healthcare Plans",
+ "Medical - Healthcare Information Services",
+ "Medical - Equipment & Services",
+ "Medical - Distribution",
+ "Medical - Diagnostics & Research",
+ "Medical - Devices",
+ "Medical - Care Facilities",
+ "Drug Manufacturers - Specialty & Generic",
+ "Drug Manufacturers - General",
+ "Biotechnology",
+ "Waste Management",
+ "Trucking",
+ "Railroads",
+ "Aerospace & Defense",
+ "Marine Shipping",
+ "Integrated Freight & Logistics",
+ "Airlines, Airports & Air Services",
+ "General Transportation",
+ "Manufacturing - Tools & Accessories",
+ "Manufacturing - Textiles",
+ "Manufacturing - Miscellaneous",
+ "Manufacturing - Metal Fabrication",
+ "Industrial - Distribution",
+ "Industrial - Specialties",
+ "Industrial - Pollution & Treatment Controls",
+ "Environmental Services",
+ "Industrial - Machinery",
+ "Industrial - Infrastructure Operations",
+ "Industrial - Capital Goods",
+ "Consulting Services",
+ "Business Equipment & Supplies",
+ "Staffing & Employment Services",
+ "Rental & Leasing Services",
+ "Engineering & Construction",
+ "Security & Protection Services",
+ "Specialty Business Services",
+ "Construction",
+ "Conglomerates",
+ "Electrical Equipment & Parts",
+ "Agricultural - Machinery",
+ "Agricultural - Commodities/Milling",
+ "REIT - Specialty",
+ "REIT - Retail",
+ "REIT - Residential",
+ "REIT - Office",
+ "REIT - Mortgage",
+ "REIT - Industrial",
+ "REIT - Hotel & Motel",
+ "REIT - Healthcare Facilities",
+ "REIT - Diversified",
+ "Real Estate - Services",
+ "Real Estate - Diversified",
+ "Real Estate - Development",
+ "Real Estate - General",
+ "Information Technology Services",
+ "Hardware, Equipment & Parts",
+ "Computer Hardware",
+ "Electronic Gaming & Multimedia",
+ "Software - Services",
+ "Software - Infrastructure",
+ "Software - Application",
+ "Semiconductors",
+ "Media & Entertainment",
+ "Communication Equipment",
+ "Technology Distributors",
+ "Consumer Electronics",
+ "Renewable Utilities",
+ "Regulated Water",
+ "Regulated Gas",
+ "Regulated Electric",
+ "Independent Power Producers",
+ "Diversified Utilities",
+ "General Utilities",
+];
diff --git a/src/routes/home/+page.svelte b/src/routes/home/+page.svelte
index e4ceb2d0..1de7280f 100644
--- a/src/routes/home/+page.svelte
+++ b/src/routes/home/+page.svelte
@@ -216,8 +216,8 @@ onMount( async() => {
-
- US Economic Indicators
+
+ Options Flow Filter
diff --git a/src/routes/stock-screener/[strategyId]/+page.svelte b/src/routes/stock-screener/[strategyId]/+page.svelte
index d0debc78..149ba494 100644
--- a/src/routes/stock-screener/[strategyId]/+page.svelte
+++ b/src/routes/stock-screener/[strategyId]/+page.svelte
@@ -3,7 +3,7 @@
import { goto} from '$app/navigation';
import { screenWidth, strategyId, numberOfUnreadNotification} from '$lib/store';
import toast from 'svelte-french-toast';
- import { abbreviateNumber, sectorList, listOfRelevantCountries } from '$lib/utils';
+ import { abbreviateNumber, sectorList, industryList, listOfRelevantCountries } from '$lib/utils';
import * as DropdownMenu from "$lib/components/shadcn/dropdown-menu/index.js";
import { Button } from "$lib/components/shadcn/button/index.js";
//const userConfirmation = confirm('Unsaved changes detected. Leaving now will discard your strategy. Continue?');
@@ -92,6 +92,8 @@ const allRules = {
growthTotalLiabilities: { label: 'Total Liabilities Growth', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
growthTotalDebt: { label: 'Total Debt Growth', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
growthTotalStockholdersEquity: { label: 'Shareholders Equity Growth', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
+ researchDevelopmentRevenueRatio: { label: 'R&D / Revenue', step: ['20%','10%','5%','1%','0%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
+
cagr3YearRevenue: { label: 'Revenue CAGR 3Y', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
cagr5YearRevenue: { label: 'Revenue CAGR 5Y', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
cagr3YearEPS: { label: 'EPS CAGR 3Y', step: ['200%','100%','50%','20%','10%','5%','1%'], category: 'fund', defaultCondition: 'over', defaultValue: '1%' },
@@ -102,6 +104,8 @@ const allRules = {
pe: { label: 'PE Ratio', step: [50,40,30,20,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: 1 },
forwardPE: { label: 'Forward PE', step: [50,20,10,5,1,0,-1,-5,-10,-20,-50], category: 'fund', defaultCondition: 'over', defaultValue: 0 },
+ forwardPS: { label: 'Forward PS', step: [50,20,10,5,1,0], category: 'fund', defaultCondition: 'over', defaultValue: 5 },
+
priceToBookRatio: { label: 'PB Ratio', step: [50,40,30,20,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: 1 },
priceToSalesRatio: { label: 'PS Ratio', step: [50,40,30,20,10,5,1], category: 'fund', defaultCondition: 'over', defaultValue: 1 },
beta: { label: 'Beta', step: [10,5,1,-5,-10], category: 'fund', defaultCondition: 'over', defaultValue: 1 },
@@ -153,6 +157,7 @@ const allRules = {
totalLiabilities: { label: 'Total Liabilities', step: ['500B','200B','100B','50B','10B','1B','100M','10M','1M'], category: 'fund', defaultCondition: 'over', defaultValue: '1M' },
analystRating: { label: 'Analyst Rating', step: ['Buy', 'Hold', 'Sell'], category: 'fund', defaultCondition: '', defaultValue: 'any' },
sector: { label: 'Sector', step: sectorList, category: 'fund', defaultCondition: '', defaultValue: 'any' },
+ industry: { label: 'Industry', step: industryList, category: 'fund', defaultCondition: '', defaultValue: 'any' },
country: { label: 'Country', step: listOfRelevantCountries, category: 'fund', defaultCondition: '', defaultValue: 'any' },
};
@@ -249,6 +254,7 @@ function handleAddRule() {
switch (ruleName) {
case 'analystRating':
case 'sector':
+ case 'industry':
case 'country':
case 'ema20':
case 'ema50':
@@ -519,7 +525,7 @@ async function handleChangeValue(value) {
} else {
checkedItems.add(value);
}
- if (['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200','analystRating','sector','country']?.includes(ruleName)) {
+ if (['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200','analystRating','sector','industry','country']?.includes(ruleName)) {
// Ensure valueMappings[ruleName] is initialized as an array
searchQuery = '';
if (!Array.isArray(valueMappings[ruleName])) {
@@ -645,7 +651,7 @@ function handleInput(event) {
if (searchQuery.length > 0) {
- const rawList = ruleName === 'country' ? listOfRelevantCountries : ruleName === 'sector' ? sectorList : ['Buy','Hold','Sell'];
+ const rawList = ruleName === 'country' ? listOfRelevantCountries : ruleName === 'sector' ? sectorList : ruleName === 'industry' ? industryList : ['Buy','Hold','Sell'];
testList = rawList?.filter(item => {
const index = item?.toLowerCase();
// Check if country starts with searchQuery
@@ -709,7 +715,7 @@ function handleInput(event) {
Stock Screener
- {ruleOfList?.length !== 0 ? filteredData?.length : 0} Matches Found
+ {filteredData?.length} Matches Found
@@ -847,7 +853,7 @@ function handleInput(event) {
- {#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'analystRating','sector','country']?.includes(row?.rule)}
+ {#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'analystRating','sector','industry','country']?.includes(row?.rule)}
@@ -870,14 +876,14 @@ function handleInput(event) {
{/if}
- {#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'analystRating','sector','country']?.includes(row?.rule)}
+ {#if !['sma20','sma50','sma100','sma200','ema20', 'ema50', 'ema100', 'ema200', 'analystRating','sector','industry','country']?.includes(row?.rule)}
{#each row?.step as newValue}
@@ -891,18 +897,18 @@ function handleInput(event) {
event.preventDefault()}>
{/each}
{:else}
- {#each (testList.length > 0 && searchQuery?.length > 0 ? testList : searchQuery?.length > 0 && testList?.length === 0 ? [] : (row?.rule === 'country' ? listOfRelevantCountries : row?.rule === 'sector' ? sectorList : ['Buy','Hold','Sell'])) as item}
+ {#each (testList.length > 0 && searchQuery?.length > 0 ? testList : searchQuery?.length > 0 && testList?.length === 0 ? [] : (row?.rule === 'country' ? listOfRelevantCountries : row?.rule === 'sector' ? sectorList : row?.rule === 'industry' ? industryList : ['Buy','Hold','Sell'])) as item}
event.preventDefault()}>
diff --git a/src/routes/stock-screener/[strategyId]/workers/filterWorker.ts b/src/routes/stock-screener/[strategyId]/workers/filterWorker.ts
index 261a1af1..a52d6eef 100644
--- a/src/routes/stock-screener/[strategyId]/workers/filterWorker.ts
+++ b/src/routes/stock-screener/[strategyId]/workers/filterWorker.ts
@@ -1,4 +1,4 @@
-import { sectorList, listOfRelevantCountries } from "$lib/utils";
+import { sectorList, industryList, listOfRelevantCountries } from "$lib/utils";
const movingAverageConditions = {
// EMA conditions
@@ -55,6 +55,7 @@ function convertUnitToValue(
const nonNumericValues = new Set([
"any",
...sectorList,
+ ...industryList,
...listOfRelevantCountries,
"hold",
"sell",
@@ -104,7 +105,9 @@ async function filterStockScreenerData(stockScreenerData, ruleOfList) {
}
// Handle categorical data like analyst ratings, sector, country
- else if (["analystRating", "sector", "country"].includes(rule.name)) {
+ else if (
+ ["analystRating", "sector", "industry", "country"].includes(rule.name)
+ ) {
if (rule.value === "any") return true;
if (Array.isArray(ruleValue) && !ruleValue.includes(itemValue))