diff --git a/src/lib/components/Options/OpenInterestByExpiry.svelte b/src/lib/components/Options/OpenInterestByExpiry.svelte new file mode 100644 index 00000000..850448ae --- /dev/null +++ b/src/lib/components/Options/OpenInterestByExpiry.svelte @@ -0,0 +1,347 @@ + + +
+

+ Open Interest (OI) By Expiry +

+ +
+ {#if options !== null} +
+ +
+ {:else} +
+
+ +
+
+ {/if} +
+
+ + + + + + {#each data?.user?.tier === "Pro" ? displayList : displayList?.slice(0, 3) as item, index} + + + + + + + + {/each} + +
+ {new Date(item?.expiry).toLocaleDateString("en-US", { + month: "short", // Abbreviated month (e.g., Jan) + day: "numeric", // Numeric day (e.g., 10) + year: "numeric", // Full year (e.g., 2025) + })} + + {@html abbreviateNumberWithColor( + item?.call_oi?.toFixed(2), + false, + true, + )} + + {@html abbreviateNumberWithColor( + item?.put_oi?.toFixed(2), + false, + true, + )} + + {#if item?.put_call_ratio <= 1 && item?.put_call_ratio !== null} + {item?.put_call_ratio?.toFixed(2)} + {:else if item?.put_call_ratio > 1 && item?.put_call_ratio !== null} + {item?.put_call_ratio?.toFixed(2)} + {:else} + n/a + {/if} +
+
+ + +
+ + diff --git a/src/lib/components/Options/OpenInterestByStrike.svelte b/src/lib/components/Options/OpenInterestByStrike.svelte new file mode 100644 index 00000000..744a818b --- /dev/null +++ b/src/lib/components/Options/OpenInterestByStrike.svelte @@ -0,0 +1,345 @@ + + +
+

+ Open Interest (OI) By Strike +

+ +
+ {#if options !== null} +
+ +
+ {:else} +
+
+ +
+
+ {/if} +
+
+ + + + + + {#each data?.user?.tier === "Pro" ? displayList : displayList?.slice(0, 3) as item, index} + + + + + + + + {/each} + +
+ {item?.strike?.toFixed(2)} + + {@html abbreviateNumberWithColor( + item?.call_oi?.toFixed(2), + false, + true, + )} + + {@html abbreviateNumberWithColor( + item?.put_oi?.toFixed(2), + false, + true, + )} + + {#if item?.put_call_ratio <= 1 && item?.put_call_ratio !== null} + {item?.put_call_ratio?.toFixed(2)} + {:else if item?.put_call_ratio > 1 && item?.put_call_ratio !== null} + {item?.put_call_ratio?.toFixed(2)} + {:else} + n/a + {/if} +
+
+ + +
+ + diff --git a/src/routes/stocks/[tickerID]/options/+layout.svelte b/src/routes/stocks/[tickerID]/options/+layout.svelte index 7bdc4dc2..b6dbeb35 100644 --- a/src/routes/stocks/[tickerID]/options/+layout.svelte +++ b/src/routes/stocks/[tickerID]/options/+layout.svelte @@ -13,6 +13,7 @@ "hottest-contracts": "/options/hottest-contracts", gex: "/options/gex", dex: "/options/dex", + oi: "/options/oi", }; if (state !== "overview" && subSectionMap[state]) { @@ -32,6 +33,7 @@ "hottest-contracts": "hottest-contracts", gex: "gex", dex: "dex", + oi: "oi", }; const foundSection = parts?.find((part) => @@ -77,6 +79,15 @@ > Hottest Contracts + changeSubSection("oi")} + class="p-2 px-5 cursor-pointer {displaySubSection === 'oi' + ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' + : 'text-gray-400 sm:hover:text-white sm:hover:bg-primary sm:hover:bg-opacity-[0.95]'}" + > + OI + changeSubSection("gex")} diff --git a/src/routes/stocks/[tickerID]/options/oi/+layout.svelte b/src/routes/stocks/[tickerID]/options/oi/+layout.svelte new file mode 100644 index 00000000..f85b92da --- /dev/null +++ b/src/routes/stocks/[tickerID]/options/oi/+layout.svelte @@ -0,0 +1,83 @@ + + +
+
+ +
+
diff --git a/src/routes/stocks/[tickerID]/options/oi/+page.server.ts b/src/routes/stocks/[tickerID]/options/oi/+page.server.ts new file mode 100644 index 00000000..da373752 --- /dev/null +++ b/src/routes/stocks/[tickerID]/options/oi/+page.server.ts @@ -0,0 +1,34 @@ + + +export const load = async ({ locals, params }) => { + const { apiKey, apiURL, user } = locals; + + const getData = async () => { + const postData = { + params: params.tickerID, + category: "strike" + }; + + const response = await fetch(apiURL + "/options-oi", { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-API-KEY": apiKey, + }, + body: JSON.stringify(postData), + }); + const output = await response.json(); + return output; + }; + + + + + + // Make sure to return a promise + return { + getData: await getData(), + }; +}; + + diff --git a/src/routes/stocks/[tickerID]/options/oi/+page.svelte b/src/routes/stocks/[tickerID]/options/oi/+page.svelte new file mode 100644 index 00000000..9bd61791 --- /dev/null +++ b/src/routes/stocks/[tickerID]/options/oi/+page.svelte @@ -0,0 +1,71 @@ + + + + + + + {$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""} + {$displayCompanyName} ({$stockTicker}) Open Interet by Strike Price · + Stocknear + + + + + + + + + + + + + + + + +
+
+
+ {#if data?.getData?.length > 0} + + {:else} +
+
+ +
+
+ {/if} +
+
+
diff --git a/src/routes/stocks/[tickerID]/options/oi/expiry/+page.server.ts b/src/routes/stocks/[tickerID]/options/oi/expiry/+page.server.ts new file mode 100644 index 00000000..f43ab639 --- /dev/null +++ b/src/routes/stocks/[tickerID]/options/oi/expiry/+page.server.ts @@ -0,0 +1,34 @@ + + +export const load = async ({ locals, params }) => { + const { apiKey, apiURL } = locals; + + const getData = async () => { + const postData = { + params: params.tickerID, + category: "expiry" + }; + + const response = await fetch(apiURL + "/options-oi", { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-API-KEY": apiKey, + }, + body: JSON.stringify(postData), + }); + const output = await response.json(); + return output; + }; + + + + + + // Make sure to return a promise + return { + getData: await getData(), + }; +}; + + diff --git a/src/routes/stocks/[tickerID]/options/oi/expiry/+page.svelte b/src/routes/stocks/[tickerID]/options/oi/expiry/+page.svelte new file mode 100644 index 00000000..c82d54aa --- /dev/null +++ b/src/routes/stocks/[tickerID]/options/oi/expiry/+page.svelte @@ -0,0 +1,70 @@ + + + + + + + {$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""} + {$displayCompanyName} ({$stockTicker}) OpenInterest by Expiry · Stocknear + + + + + + + + + + + + + + + + +
+
+
+ {#if rawData?.length > 0} + + {:else} +
+
+ +
+
+ {/if} +
+
+