add exactly condition to options flow page

This commit is contained in:
MuslemRahimi 2024-12-14 21:01:33 +01:00
parent e508e6a9ab
commit 32db538ed9
4 changed files with 54 additions and 33 deletions

33
package-lock.json generated
View File

@ -13,6 +13,7 @@
"greeks": "^1.0.0",
"html2canvas": "^1.4.1",
"https": "^1.0.0",
"jsconfig.json": "^2.3.3",
"marked": "^12.0.2",
"mode-watcher": "^0.3.1",
"sharp": "^0.33.5",
@ -4006,7 +4007,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -4574,7 +4574,6 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
@ -5090,7 +5089,6 @@
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -5281,8 +5279,7 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/entities": {
"version": "4.5.0",
@ -5371,7 +5368,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -5677,7 +5673,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@ -6097,7 +6092,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -6228,6 +6222,20 @@
"integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==",
"dev": true
},
"node_modules/jsconfig.json": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/jsconfig.json/-/jsconfig.json-2.3.3.tgz",
"integrity": "sha512-why4CyeZ6NDeOEtm+c7Pq5LyD6JHlBDiNvjVAR5Ynp1tsgpmS/fcm9Se8FLZwBYmhvUGRji1D8ZbXDIsXGJGPw==",
"license": "MIT",
"dependencies": {
"deepmerge": "^4.2.2",
"picocolors": "^1.0.0",
"yargs": "^17.2.1"
},
"bin": {
"jsconfig.json": "bin/cli.js"
}
},
"node_modules/jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@ -7124,7 +7132,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
@ -7506,7 +7513,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -7900,7 +7906,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -7929,7 +7934,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -9044,7 +9048,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@ -9094,7 +9097,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@ -9115,7 +9117,6 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
"engines": {
"node": ">=10"
}
@ -9145,7 +9146,6 @@
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dev": true,
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
@ -9163,7 +9163,6 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
"engines": {
"node": ">=12"
}

View File

@ -98,6 +98,7 @@
"greeks": "^1.0.0",
"html2canvas": "^1.4.1",
"https": "^1.0.0",
"jsconfig.json": "^2.3.3",
"marked": "^12.0.2",
"mode-watcher": "^0.3.1",
"sharp": "^0.33.5",

View File

@ -467,6 +467,10 @@
}
}
const currentTime = new Date(
new Date().toLocaleString("en-US", { timeZone: "America/New_York" }),
)?.getTime();
const nyseDate = new Date(
data?.getOptionsFlowFeed?.at(0)?.date ?? null,
)?.toLocaleString("en-US", {
@ -601,7 +605,6 @@
function daysLeft(targetDate) {
const targetTime = new Date(targetDate).getTime();
const currentTime = new Date().getTime();
const difference = targetTime - currentTime;
const millisecondsPerDay = 1000 * 60 * 60 * 24;
@ -1167,7 +1170,8 @@
{:else}
{ruleCondition[row?.rule]
?.replace("under", "Under")
?.replace("over", "Over") ?? ""}
?.replace("over", "Over")
?.replace("exactly", "Exactly") ?? ""}
{valueMappings[row?.rule]}
{/if}
</span>
@ -1212,7 +1216,8 @@
{ruleCondition[ruleName]
?.replace("under", "Under")
?.replace("over", "Over")
?.replace("between", "Between")}
?.replace("between", "Between")
?.replace("exactly", "Exactly")}
</span>
<svg
class="mt-1 -mr-1 ml-1 h-5 w-5 xs:ml-2 !ml-0 sm:ml-0 inline-block"
@ -1230,7 +1235,7 @@
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
{#each ["Over", "Under", "Between"] as item}
{#each ["Over", "Under", "Between", "Exactly"] as item}
<DropdownMenu.Item
on:click={() =>
changeRuleCondition(
@ -1291,7 +1296,7 @@
/>
{/if}
{#if ["over", "under"]?.includes(ruleCondition[ruleName]?.toLowerCase())}
{#if ["over", "under", "exactly"]?.includes(ruleCondition[ruleName]?.toLowerCase())}
<div
class="ml-2 flex touch-manipulation flex-row items-center gap-x-1.5"
>
@ -1387,7 +1392,8 @@
>
{ruleCondition[row?.rule]
?.replace("under", "Under")
?.replace("over", "Over")}
?.replace("over", "Over")
?.replace("exactly", "Exactly")}
{newValue}
</button>
</DropdownMenu.Item>

View File

@ -137,7 +137,7 @@ if (ruleName === 'volumeoiratio') {
return false;
}
const ratio = (volume / openInterest) * 100;
const ratio = Math.ceil((volume / openInterest) * 100);
// Handle 'between' condition for volume to open interest ratio
if (rule.condition === 'between' && Array.isArray(ruleValue)) {
@ -153,6 +153,8 @@ if (ruleName === 'volumeoiratio') {
// Existing conditions for 'over' and 'under'
if (rule.condition === 'over' && ratio <= ruleValue) return false;
if (rule.condition === 'under' && ratio >= ruleValue) return false;
if (rule.condition === 'exactly' && ratio !== ruleValue) return false;
return true;
};
@ -167,7 +169,7 @@ if (ruleName === 'sizeoiratio') {
return false;
}
const ratio = (size / openInterest) * 100;
const ratio = Math?.ceil((size / openInterest) * 100);
// Handle 'between' condition for size to open interest ratio
if (rule.condition === 'between' && Array.isArray(ruleValue)) {
@ -183,6 +185,8 @@ if (ruleName === 'sizeoiratio') {
// Existing conditions for 'over' and 'under'
if (rule.condition === 'over' && ratio <= ruleValue) return false;
if (rule.condition === 'under' && ratio >= ruleValue) return false;
if (rule.condition === 'exactly' && ratio !== ruleValue) return false;
return true;
};
@ -200,7 +204,8 @@ if (ruleName === 'sizeoiratio') {
const expirationDate = new Date(item[rule.name]);
if (isNaN(expirationDate)) return false; // Handle invalid dates
const daysDiff = (expirationDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
const daysDiff = Math?.ceil((expirationDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
if (rule.condition === 'between' && Array.isArray(ruleValue)) {
const [minDays, maxDays] = ruleValue.map(val =>
@ -221,6 +226,11 @@ if (ruleName === 'sizeoiratio') {
if (rule.condition === 'under' && typeof ruleValue === 'number') {
return daysDiff <= ruleValue;
}
if (rule.condition === 'exactly' && typeof ruleValue === 'number') {
return daysDiff === ruleValue;
}
return false;
};
@ -236,9 +246,9 @@ if (ruleName === 'sizeoiratio') {
const itemValue = item[rule.name];
// Handle array of values for categorical fields
if (Array.isArray(ruleValue)) {
if (Array?.isArray(ruleValue)) {
// Remove any empty or undefined values from ruleValue
const validRuleValues = ruleValue.filter(val => val !== "" && val !== undefined);
const validRuleValues = ruleValue?.filter(val => val !== "" && val !== undefined);
// If no valid values remain, return true for all items
if (validRuleValues.length === 0) {
@ -246,14 +256,14 @@ if (ruleName === 'sizeoiratio') {
}
// If itemValue is an array, check if any of the values match
if (Array.isArray(itemValue)) {
return validRuleValues.some(val =>
if (Array?.isArray(itemValue)) {
return validRuleValues?.some(val =>
itemValue.some(iv => iv.toLowerCase() === val.toLowerCase())
);
}
// If itemValue is a string, check if it's in the validRuleValues array
return validRuleValues.some(val =>
return validRuleValues?.some(val =>
itemValue?.toLowerCase() === val.toLowerCase()
);
}
@ -261,8 +271,8 @@ if (ruleName === 'sizeoiratio') {
// Handle single string value
if (typeof ruleValue === 'string') {
// If itemValue is an array, check if any value matches
if (Array.isArray(itemValue)) {
return itemValue.some(iv => iv.toLowerCase() === ruleValue.toLowerCase());
if (Array?.isArray(itemValue)) {
return itemValue?.some(iv => iv.toLowerCase() === ruleValue.toLowerCase());
}
// If both are strings, do a direct comparison
@ -281,6 +291,8 @@ return (item) => {
if (itemValue === null || itemValue === undefined) return false;
const numericItemValue = parseFloat(itemValue);
if (isNaN(numericItemValue)) return false;
// Handle 'between' condition for numeric fields using convertUnitToValue
@ -295,9 +307,12 @@ return (item) => {
}
// Existing conditions
if (rule.condition === 'exactly' && numericItemValue !== ruleValue) return false;
if (rule.condition === 'over' && numericItemValue <= ruleValue) return false;
if (rule.condition === 'under' && numericItemValue >= ruleValue) return false;
return true;
};