add repeated flow
This commit is contained in:
parent
2471ce872a
commit
2026bb5ed0
@ -95,6 +95,11 @@
|
|||||||
step: ["ITM", "OTM"],
|
step: ["ITM", "OTM"],
|
||||||
defaultValue: "any",
|
defaultValue: "any",
|
||||||
},
|
},
|
||||||
|
flowType: {
|
||||||
|
label: "Flow Type",
|
||||||
|
step: ["Repeated Flow"],
|
||||||
|
defaultValue: "any",
|
||||||
|
},
|
||||||
put_call: {
|
put_call: {
|
||||||
label: "Contract Type",
|
label: "Contract Type",
|
||||||
step: ["Calls", "Puts"],
|
step: ["Calls", "Puts"],
|
||||||
@ -128,6 +133,16 @@
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const categoricalRules = [
|
||||||
|
"moneyness",
|
||||||
|
"flowType",
|
||||||
|
"put_call",
|
||||||
|
"sentiment",
|
||||||
|
"execution_estimate",
|
||||||
|
"option_activity_type",
|
||||||
|
"underlying_type",
|
||||||
|
];
|
||||||
|
|
||||||
// Generate allRows from allRules
|
// Generate allRows from allRules
|
||||||
$: allRows = Object?.entries(allRules)
|
$: allRows = Object?.entries(allRules)
|
||||||
?.sort(([, a], [, b]) => a.label.localeCompare(b.label)) // Sort by label
|
?.sort(([, a], [, b]) => a.label.localeCompare(b.label)) // Sort by label
|
||||||
@ -218,6 +233,7 @@
|
|||||||
|
|
||||||
switch (ruleName) {
|
switch (ruleName) {
|
||||||
case "moneyness":
|
case "moneyness":
|
||||||
|
case "flowType":
|
||||||
case "put_call":
|
case "put_call":
|
||||||
case "sentiment":
|
case "sentiment":
|
||||||
case "execution_estimate":
|
case "execution_estimate":
|
||||||
@ -347,16 +363,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Specific rule handling for options-related rules
|
// Specific rule handling for options-related rules
|
||||||
if (
|
if (categoricalRules?.includes(ruleName)) {
|
||||||
[
|
|
||||||
"moneyness",
|
|
||||||
"put_call",
|
|
||||||
"sentiment",
|
|
||||||
"execution_estimate",
|
|
||||||
"option_activity_type",
|
|
||||||
"underlying_type",
|
|
||||||
]?.includes(ruleName)
|
|
||||||
) {
|
|
||||||
// Ensure valueMappings[ruleName] is initialized as an array
|
// Ensure valueMappings[ruleName] is initialized as an array
|
||||||
if (!Array.isArray(valueMappings[ruleName])) {
|
if (!Array.isArray(valueMappings[ruleName])) {
|
||||||
valueMappings[ruleName] = [];
|
valueMappings[ruleName] = [];
|
||||||
@ -1130,7 +1137,7 @@
|
|||||||
<DropdownMenu.Content
|
<DropdownMenu.Content
|
||||||
class="w-64 min-h-auto max-h-72 overflow-y-auto scroller"
|
class="w-64 min-h-auto max-h-72 overflow-y-auto scroller"
|
||||||
>
|
>
|
||||||
{#if !["moneyness", "put_call", "sentiment", "execution_estimate", "option_activity_type", "underlying_type"]?.includes(row?.rule)}
|
{#if !categoricalRules?.includes(row?.rule)}
|
||||||
<DropdownMenu.Label
|
<DropdownMenu.Label
|
||||||
class="absolute mt-2 h-11 border-gray-800 border-b -top-1 z-20 fixed sticky bg-[#09090B]"
|
class="absolute mt-2 h-11 border-gray-800 border-b -top-1 z-20 fixed sticky bg-[#09090B]"
|
||||||
>
|
>
|
||||||
@ -1290,7 +1297,7 @@
|
|||||||
></div>
|
></div>
|
||||||
{/if}
|
{/if}
|
||||||
<DropdownMenu.Group class="min-h-10 mt-2">
|
<DropdownMenu.Group class="min-h-10 mt-2">
|
||||||
{#if !["moneyness", "put_call", "sentiment", "execution_estimate", "option_activity_type", "underlying_type"]?.includes(row?.rule)}
|
{#if !categoricalRules?.includes(row?.rule)}
|
||||||
{#each row?.step as newValue, index}
|
{#each row?.step as newValue, index}
|
||||||
{#if ruleCondition[row?.rule] === "between"}
|
{#if ruleCondition[row?.rule] === "between"}
|
||||||
{#if newValue && row?.step[index + 1]}
|
{#if newValue && row?.step[index + 1]}
|
||||||
@ -1334,7 +1341,7 @@
|
|||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{:else if ["moneyness", "put_call", "sentiment", "execution_estimate", "option_activity_type", "underlying_type"]?.includes(row?.rule)}
|
{:else if categoricalRules?.includes(row?.rule)}
|
||||||
{#each row?.step as item}
|
{#each row?.step as item}
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
class="sm:hover:bg-[#2A2E39]"
|
class="sm:hover:bg-[#2A2E39]"
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
|
|
||||||
|
interface FilterContext {
|
||||||
|
flowTypeCache?: Map<string, number>;
|
||||||
|
}
|
||||||
|
|
||||||
const categoricalFields = [
|
const categoricalFields = [
|
||||||
'put_call',
|
'put_call',
|
||||||
'sentiment',
|
'sentiment',
|
||||||
@ -36,6 +40,7 @@ function convertUnitToValue(
|
|||||||
"etf",
|
"etf",
|
||||||
"itm",
|
"itm",
|
||||||
"otm",
|
"otm",
|
||||||
|
"repeated flow"
|
||||||
]);
|
]);
|
||||||
if (nonNumericValues.has(lowerInput)) return input;
|
if (nonNumericValues.has(lowerInput)) return input;
|
||||||
if (input.endsWith("%")) {
|
if (input.endsWith("%")) {
|
||||||
@ -72,10 +77,38 @@ function createRuleCheck(rule, ruleName, ruleValue) {
|
|||||||
const now = new Date(new Date().toLocaleString("en-US", { timeZone: "America/New_York" }));
|
const now = new Date(new Date().toLocaleString("en-US", { timeZone: "America/New_York" }));
|
||||||
|
|
||||||
|
|
||||||
|
if (ruleName === 'flowtype') {
|
||||||
|
return (item: any, context: FilterContext = {}) => {
|
||||||
|
// Check for 'any' rule or other non-repeated flow conditions
|
||||||
|
if (ruleValue === 'any' || ruleValue?.includes("any")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Repeated Flow logic
|
||||||
|
if (ruleValue?.includes('Repeated Flow')) {
|
||||||
|
// Initialize flowTypeCache if it doesn't exist
|
||||||
|
context.flowTypeCache = context.flowTypeCache || new Map();
|
||||||
|
|
||||||
|
// Create a unique key for repeated flow based on item characteristics
|
||||||
|
const key = `${item.ticker}-${item.put_call}-${item.strike_price}-${item.date_expiration}`;
|
||||||
|
|
||||||
|
// Increment the count for the key in the flowTypeCache
|
||||||
|
const currentCount = (context.flowTypeCache.get(key) || 0) + 1;
|
||||||
|
context.flowTypeCache.set(key, currentCount);
|
||||||
|
|
||||||
|
// Return true if this flow appears more than N times (3 in this case)
|
||||||
|
return currentCount > 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback for other flow type conditions (i.e., non-repeated flow)
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ruleName === 'moneyness') {
|
if (ruleName === 'moneyness') {
|
||||||
return (item) => {
|
return (item) => {
|
||||||
|
if (ruleValue === 'any' || ruleValue?.includes("any")) return true;
|
||||||
if (ruleValue === 'any') return true;
|
|
||||||
|
|
||||||
const currentPrice = parseFloat(item?.underlying_price);
|
const currentPrice = parseFloat(item?.underlying_price);
|
||||||
const strikePrice = parseFloat(item?.strike_price);
|
const strikePrice = parseFloat(item?.strike_price);
|
||||||
@ -280,11 +313,16 @@ async function filterRawData(rawData, ruleOfList, filterQuery) {
|
|||||||
|
|
||||||
// Preprocess filter tickers
|
// Preprocess filter tickers
|
||||||
const filterTickers = filterQuery
|
const filterTickers = filterQuery
|
||||||
? filterQuery.split(",").map((ticker) => ticker.trim().toUpperCase())
|
? filterQuery?.split(",").map((ticker) => ticker.trim().toUpperCase())
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
// Initialize context with optional flowTypeCache
|
||||||
|
const context: FilterContext = {
|
||||||
|
flowTypeCache: new Map()
|
||||||
|
};
|
||||||
|
|
||||||
// Precompile rules for more efficient filtering
|
// Precompile rules for more efficient filtering
|
||||||
const compiledRules = ruleOfList.map(rule => {
|
const compiledRules = ruleOfList?.map(rule => {
|
||||||
const ruleName = rule?.name?.toLowerCase();
|
const ruleName = rule?.name?.toLowerCase();
|
||||||
const ruleValue = convertUnitToValue(rule.value);
|
const ruleValue = convertUnitToValue(rule.value);
|
||||||
|
|
||||||
@ -302,12 +340,12 @@ async function filterRawData(rawData, ruleOfList, filterQuery) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply all precompiled rules
|
// Apply all precompiled rules, passing the context
|
||||||
return compiledRules.every(rule => rule?.compiledCheck(item));
|
return compiledRules?.every(rule => rule?.compiledCheck(item, context));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Web Worker message handler
|
// Web Worker message handler remains the same
|
||||||
onmessage = async (event: MessageEvent) => {
|
onmessage = async (event: MessageEvent) => {
|
||||||
const { rawData, ruleOfList, filterQuery } = event.data || {};
|
const { rawData, ruleOfList, filterQuery } = event.data || {};
|
||||||
// Filter the data
|
// Filter the data
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user