add top analyst rule
This commit is contained in:
parent
1e2f545af0
commit
2660c0b822
@ -146,6 +146,10 @@
|
||||
rule: "institutionalOwnership",
|
||||
type: "percent",
|
||||
},
|
||||
{ name: "Top Analyst Rating", rule: "topAnalystRating", type: "rating" },
|
||||
{ name: "Top Analyst Count", rule: "topAnalystCounter", type: "int" },
|
||||
{ name: "Top Analyst Price Target", rule: "topAnalystPriceTarget", type: "float" },
|
||||
{ name: "Top Analyst PT Upside", rule: "topAnalystUpside", type: "percentSign" },
|
||||
];
|
||||
|
||||
allRows = [...allRows, ...specificRows];
|
||||
@ -543,8 +547,8 @@
|
||||
const preferredOrder = ["rank", "symbol", "name"];
|
||||
|
||||
// Create a mapping of rule to name and type from allRows
|
||||
const ruleToMetadataMap = Object.fromEntries(
|
||||
allRows.map((row) => [row.rule, { name: row.name, type: row.type }]),
|
||||
const ruleToMetadataMap = Object?.fromEntries(
|
||||
allRows?.map((row) => [row.rule, { name: row.name, type: row.type }]),
|
||||
);
|
||||
|
||||
// Separate preferred keys and other keys, excluding "type"
|
||||
|
||||
@ -8,19 +8,19 @@
|
||||
|
||||
const rawData = data?.getTopAnalystStocks;
|
||||
const excludedRules = new Set([
|
||||
"upside",
|
||||
"priceTarget",
|
||||
"topAnalystUpside",
|
||||
"topAnalystPriceTarget",
|
||||
"topAnalystCounter",
|
||||
"marketCap",
|
||||
"analystCounter",
|
||||
"analystRating"
|
||||
"topAnalystRating"
|
||||
]);
|
||||
|
||||
const defaultList = [
|
||||
{ name: "Analyst Count", rule: "analystCounter" },
|
||||
{ name: "Upside", rule: "upside" },
|
||||
{ name: "Price Target", rule: "priceTarget" },
|
||||
{ name: "Market Cap", rule: "marketCap" },
|
||||
{name: 'Analyst Rating', rule: 'analystRating'}
|
||||
{ name: "Top Analyst Count", rule: "topAnalystCounter" },
|
||||
{ name: "Top Analyst PT Upside", rule: "topAnalystUpside" },
|
||||
{ name: "Top Analyst Price Target", rule: "topAnalystPriceTarget" },
|
||||
{name: 'Top Analyst Rating', rule: 'topAnalystRating'},
|
||||
{name: 'Market Cap', rule: 'marketCap'}
|
||||
];
|
||||
const hideLastRow = true;
|
||||
</script>
|
||||
@ -74,7 +74,7 @@
|
||||
<div
|
||||
class="relative flex justify-center items-start overflow-hidden w-full"
|
||||
>
|
||||
<main class="w-full lg:w-3/4 lg:pr-5">
|
||||
<main class="w-full lg:pr-5">
|
||||
<div class="mb-6 border-b-[2px]">
|
||||
<h1 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
||||
Top Strong Buy Stocks
|
||||
@ -255,66 +255,6 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<aside class="hidden lg:block relative fixed w-1/4 ml-4">
|
||||
{#if data?.user?.tier !== "Pro"}
|
||||
<div
|
||||
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer"
|
||||
>
|
||||
<a
|
||||
href={"/pricing"}
|
||||
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
|
||||
>
|
||||
<div class="w-full flex justify-between items-center p-3 mt-3">
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Pro Subscription
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Upgrade now for unlimited access to all data and tools
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer"
|
||||
>
|
||||
<a
|
||||
href={"/analysts"}
|
||||
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
|
||||
>
|
||||
<div class="w-full flex justify-between items-center p-3 mt-3">
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Analyst
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Get the latest top Wall Street analyst ratings
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer"
|
||||
>
|
||||
<a
|
||||
href={"/most-shorted-stocks"}
|
||||
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
|
||||
>
|
||||
<div class="w-full flex justify-between items-center p-3 mt-3">
|
||||
<h2 class="text-start text-xl font-semibold text-white ml-3">
|
||||
Top Shorted Stocks
|
||||
</h2>
|
||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||
</div>
|
||||
<span class="text-white p-3 ml-3 mr-3">
|
||||
Never miss out another short squeeze
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1296,14 +1296,43 @@
|
||||
category: "Forecasts, Analysts & Price Targets",
|
||||
},
|
||||
upside: {
|
||||
label: "Price Target Upside [%]",
|
||||
label: "Price Target Upside",
|
||||
step: ["100%", "50%", "20%", "10%", "5%", "0%"],
|
||||
|
||||
defaultCondition: "over",
|
||||
defaultValue: "any",
|
||||
category: "Forecasts, Analysts & Price Targets",
|
||||
},
|
||||
topAnalystRating: {
|
||||
label: "Top Analyst Rating",
|
||||
step: ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"],
|
||||
defaultCondition: "",
|
||||
defaultValue: "any",
|
||||
category: "Forecasts, Analysts & Price Targets",
|
||||
},
|
||||
topAnalystCounter: {
|
||||
label: "Top Analyst Count",
|
||||
step: ["10", "5", "3", "1"],
|
||||
|
||||
defaultCondition: "over",
|
||||
defaultValue: "any",
|
||||
category: "Forecasts, Analysts & Price Targets",
|
||||
},
|
||||
topAnalystUpside: {
|
||||
label: "Top Analyst Price Target Upside",
|
||||
step: ["100%", "50%", "20%", "10%", "5%", "0%"],
|
||||
|
||||
defaultCondition: "over",
|
||||
defaultValue: "any",
|
||||
category: "Forecasts, Analysts & Price Targets",
|
||||
},
|
||||
topAnalystPriceTarget: {
|
||||
label: "Top Analyst Price Target",
|
||||
step: ["1000", "500", "100", "10", "5", "1"],
|
||||
defaultCondition: "over",
|
||||
defaultValue: "any",
|
||||
category: "Forecasts, Analysts & Price Targets",
|
||||
},
|
||||
halalStocks: {
|
||||
label: "Halal Stocks",
|
||||
step: ["Compliant", "Non-Compliant"],
|
||||
@ -1452,6 +1481,7 @@
|
||||
?.filter((rule) =>
|
||||
[
|
||||
"analystRating",
|
||||
"topAnalystRating",
|
||||
"halalStocks",
|
||||
"sector",
|
||||
"country",
|
||||
@ -1555,6 +1585,7 @@
|
||||
?.filter((rule) =>
|
||||
[
|
||||
"analystRating",
|
||||
"topAnalystRating",
|
||||
"halalStocks",
|
||||
"sector",
|
||||
"country",
|
||||
@ -1569,7 +1600,7 @@
|
||||
}
|
||||
|
||||
function changeRule(state: string) {
|
||||
if (data?.user?.tier !== "Pro" && state === "score") {
|
||||
if (data?.user?.tier !== "Pro" && ['topAnalystRating','topAnalystCounter','topAnalystPriceTarget','topAnalystUpside','score']?.includes(state)) {
|
||||
goto("/pricing");
|
||||
} else {
|
||||
selectedPopularStrategy = "";
|
||||
@ -1628,6 +1659,7 @@
|
||||
|
||||
switch (ruleName) {
|
||||
case "analystRating":
|
||||
case "topAnalystRating":
|
||||
case "halalStocks":
|
||||
case "score":
|
||||
case "sector":
|
||||
@ -1862,6 +1894,7 @@ const handleKeyDown = (event) => {
|
||||
?.filter((rule) =>
|
||||
[
|
||||
"analystRating",
|
||||
"topAnalystRating",
|
||||
"halalStocks",
|
||||
"sector",
|
||||
"country",
|
||||
@ -1949,6 +1982,7 @@ const handleKeyDown = (event) => {
|
||||
"ema200",
|
||||
"grahamNumber",
|
||||
"analystRating",
|
||||
"topAnalystRating",
|
||||
"halalStocks",
|
||||
"score",
|
||||
"sector",
|
||||
@ -2112,7 +2146,7 @@ const handleKeyDown = (event) => {
|
||||
? sectorList
|
||||
: ruleName === "industry"
|
||||
? industryList
|
||||
: ruleName === "analystRating" || ruleName === "score"
|
||||
: ['analystRating','topAnalystRating','score']?.includes(ruleName)
|
||||
? ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"]
|
||||
: ["Compliant", "Non-Compliant"];
|
||||
testList =
|
||||
@ -2213,6 +2247,7 @@ const handleKeyDown = (event) => {
|
||||
"score",
|
||||
"sector",
|
||||
"analystRating",
|
||||
"topAnalystRating",
|
||||
"halalStocks",
|
||||
];
|
||||
|
||||
@ -2797,7 +2832,7 @@ const handleKeyDown = (event) => {
|
||||
<DropdownMenu.Content
|
||||
class="w-64 min-h-auto max-h-72 overflow-y-auto scroller"
|
||||
>
|
||||
{#if !["sma20", "sma50", "sma100", "sma200", "ema20", "ema50", "ema100", "ema200", "grahamNumber", "analystRating", "halalStocks", "score", "sector", "industry", "country"]?.includes(row?.rule)}
|
||||
{#if !["sma20", "sma50", "sma100", "sma200", "ema20", "ema50", "ema100", "ema200", "grahamNumber", "analystRating", "topAnalystRating", "halalStocks", "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]"
|
||||
>
|
||||
@ -2960,6 +2995,7 @@ const handleKeyDown = (event) => {
|
||||
autocomplete="off"
|
||||
class="{![
|
||||
'analystRating',
|
||||
"topAnalystRating",
|
||||
'halalStocks',
|
||||
'score',
|
||||
'sector',
|
||||
@ -2975,7 +3011,7 @@ const handleKeyDown = (event) => {
|
||||
</div>
|
||||
{/if}
|
||||
<DropdownMenu.Group class="min-h-10 mt-2">
|
||||
{#if !["sma20", "sma50", "sma100", "sma200", "ema20", "ema50", "ema100", "ema200", "grahamNumber", "analystRating", "halalStocks", "score", "sector", "industry", "country"]?.includes(row?.rule)}
|
||||
{#if !["sma20", "sma50", "sma100", "sma200", "ema20", "ema50", "ema100", "ema200", "grahamNumber", "analystRating", "topAnalystRating","halalStocks", "score", "sector", "industry", "country"]?.includes(row?.rule)}
|
||||
{#each row?.step as newValue, index}
|
||||
{#if ruleCondition[row?.rule] === "between"}
|
||||
{#if newValue && row?.step[index + 1]}
|
||||
@ -3044,7 +3080,7 @@ const handleKeyDown = (event) => {
|
||||
</DropdownMenu.Item>
|
||||
{/each}
|
||||
{:else}
|
||||
{#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 : ruleName === "analystRating" || ruleName === "score" ? ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"] : ["Compliant", "Non-Compliant"] 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 : ['analystRating','topAnalystRating','score']?.includes(ruleName) ? ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"] : ["Compliant", "Non-Compliant"] as item}
|
||||
<DropdownMenu.Item class="sm:hover:bg-primary">
|
||||
<div
|
||||
class="flex items-center"
|
||||
@ -3285,7 +3321,7 @@ const handleKeyDown = (event) => {
|
||||
<td
|
||||
class="whitespace-nowrap text-sm sm:text-[1rem] text-end text-white border-b-[#09090B]"
|
||||
>
|
||||
{#if ["ema20", "ema50", "ema100", "ema200", "analystRating", "halalStocks", "score", "sector", "industry", "country"]?.includes(row?.rule)}
|
||||
{#if ["ema20", "ema50", "ema100", "ema200", "analystRating", "topAnalystRating", "halalStocks", "score", "sector", "industry", "country"]?.includes(row?.rule)}
|
||||
{item[row?.rule]}
|
||||
{:else}
|
||||
{abbreviateNumber(item[row?.rule])}
|
||||
@ -3413,7 +3449,7 @@ const handleKeyDown = (event) => {
|
||||
>
|
||||
{/if}
|
||||
|
||||
{:else if row?.rule === 'analystRating'}
|
||||
{:else if ['analystRating','topAnalystRating']?.includes(row?.rule)}
|
||||
{#if ["Strong Buy", "Buy"].includes(item[row?.rule])}
|
||||
<span class="text-[#00FC50]">{item[row?.rule]}</span>
|
||||
{:else if ["Strong Sell", "Sell"].includes(item[row?.rule])}
|
||||
@ -3593,7 +3629,7 @@ const handleKeyDown = (event) => {
|
||||
<div
|
||||
class="flex w-full items-center space-x-1.5 py-1.5 md:w-1/2 lg:w-1/3 lg:py-1"
|
||||
>
|
||||
{#if row?.rule === "score" && data?.user?.tier !== "Pro"}
|
||||
{#if ['topAnalystRating','topAnalystCounter','topAnalystPriceTarget','topAnalystUpside','score']?.includes(row?.rule) && data?.user?.tier !== "Pro"}
|
||||
<label id={row?.rule} on:click={() => changeRule(row?.rule)}>
|
||||
<svg
|
||||
class="w-4 h-4 mb-1 inline-block text-[#A3A3A3] sm:hover:text-white cursor-pointer"
|
||||
|
||||
@ -112,7 +112,7 @@ function createRuleCheck(rule, ruleName, ruleValue) {
|
||||
|
||||
// Categorical checks
|
||||
const categoricalFields = [
|
||||
'analystRating', 'halalStocks', 'score',
|
||||
'analystRating', 'topAnalystRating', 'halalStocks', 'score',
|
||||
'sector', 'industry', 'country'
|
||||
];
|
||||
|
||||
|
||||
@ -17,9 +17,9 @@
|
||||
let rawData = data?.getAnalystTickerHistory ?? [];
|
||||
let historyList = [];
|
||||
let priceTarget = "n/a";
|
||||
let numOfAnalyst = 0;
|
||||
let numOfAnalyst = "n/a";
|
||||
let consensusRating = "n/a";
|
||||
let changesPercentage = 0;
|
||||
let changesPercentage = "n/a";
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
@ -62,7 +62,7 @@
|
||||
const key = `${entry.analyst}-${entry.name}`;
|
||||
|
||||
// Convert date and time to a Date object
|
||||
const dateTimeStr = `${entry.date} ${entry.time}`;
|
||||
const dateTimeStr = `${entry.date}`;
|
||||
const dateTime = new Date(dateTimeStr);
|
||||
|
||||
// Check if this entry is the latest for the given key
|
||||
@ -96,7 +96,7 @@
|
||||
})
|
||||
?.slice(0, 30); //Consider only the last 30 ratings in the last 12 months
|
||||
|
||||
const filteredAnalystCount = recentData?.length;
|
||||
const filteredAnalystCount = recentData?.length ?? 'n/a';
|
||||
const priceTargets = recentData
|
||||
?.map((item) => parseFloat(item.adjusted_pt_current))
|
||||
?.filter((pt) => !isNaN(pt));
|
||||
@ -104,9 +104,9 @@
|
||||
? priceTargets?.sort((a, b) => a - b)[
|
||||
Math.floor(priceTargets?.length / 2)
|
||||
]
|
||||
: "-";
|
||||
: "n/a";
|
||||
|
||||
numOfAnalyst = filteredAnalystCount;
|
||||
numOfAnalyst = filteredAnalystCount === 0 ? 'n/a' : filteredAnalystCount;
|
||||
priceTarget = medianPriceTarget;
|
||||
changesPercentage =
|
||||
medianPriceTarget !== "-" && data?.getStockQuote?.price != null
|
||||
@ -141,7 +141,8 @@
|
||||
? "Hold"
|
||||
: averageRatingScore >= 1.5
|
||||
? "Sell"
|
||||
: "Strong Sell";
|
||||
: averageRatingScore >= 1
|
||||
? "Strong Sell" : 'n/a';
|
||||
|
||||
rawData = recentData;
|
||||
historyList = rawData.slice(0, 50);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user