+
+
+
+ Unsual Options Activity
+
+
+
+
+
+ {#if optionsPlotData?.length !== 0}
+ 1 Year of options activity involving {$displayCompanyName} by major institutional traders and hedge funds.
+ {:else}
+ There's no data available, indicating that major traders may not be actively betting on {$displayCompanyName}.
+ {/if}
+
+
+
+
+
+
+ {#if optionsPlotData?.length !== 0}
+
+
+
+
Total Volume
-
-
-
-
{displayTotalVolume}
+
+
+
+
+
+
+
+
+
+
+ {displayTotalVolume}
+
-
-
-
-
-
-
- Total OI
-
-
-
-
-
{displayTotalOpenInterest}
+
+
+ Total OI
+
+
+
+
+
+
+
+
+
+
+ {displayTotalOpenInterest}
+
-
-
-
-
- P/C Ratio
-
-
-
-
- {totalPutCallRatio !== 'Infinity' ? totalPutCallRatio : '> 1'}
-
+
+
+ P/C Ratio
+
+
+
+
+
+
+
+
+
+
+ {putCallRatio !== 'Infinity' ? putCallRatio : '> 1'}
+
-
-
-
-
+
+
OI P/C Ratio
-
-
-
-
{putCallOpenInterestRatio !== 'Infinity' ? putCallOpenInterestRatio : '> 1'}
+
+
+
+
+
+
+
+
+
+
+ {putCallOpenInterestRatio !== 'Infinity' ? putCallOpenInterestRatio : '> 1'}
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ Choose a time period
+ 1 Week
+ 1 Month
+ 3 Months
+ 6 Months
+ 1 Year
+
+
+
Choose a category
Volume
Open Interest
-
-
-
-
+
+
+
+
+
+
+
+ {#if filteredList?.length !== 0}
-
-
-
-
-
- Latest Options Activity
-
-
-
-
- {#if optionList?.length !== 0}
-
-
-
-
-
-
+ {:else}
+
+
+
+ No Options activity found
+
+
+ {/if}
+
+
+
+
+
+ Latest Options Activity
+
+
+
+
+ {#if optionList?.length !== 0}
+
+
+
+
+
+
+
+ Flow Sentiment
+ {flowSentiment}
+
+
+
+
+
+
- Flow Sentiment
- {flowSentiment}
+ Put/Call
+
+ {latestPutCallRatio?.toFixed(3)}
+
-
+
+
+
+
+
+
+
+ =1 ? 0 : 100-(latestPutCallRatio*100)?.toFixed(2)}>
+
+
+
+
+ {latestPutCallRatio?.toFixed(2)}
+
+
+
+
-
-
+
+
- Put/Call
+ Call Flow
- {latestPutCallRatio?.toFixed(3)}
-
-
-
-
-
-
-
-
-
- =1 ? 0 : 100-(latestPutCallRatio*100)?.toFixed(2)}>
-
-
-
-
- {latestPutCallRatio?.toFixed(2)}
-
-
-
-
-
-
-
-
-
- Call Flow
-
- {new Intl.NumberFormat("en", {
- minimumFractionDigits: 0,
- maximumFractionDigits: 0
- }).format(displayCallVolume)}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {callPercentage}%
-
-
-
-
-
-
-
-
- Put Flow
-
- {new Intl.NumberFormat("en", {
- minimumFractionDigits: 0,
- maximumFractionDigits: 0
- }).format(displayPutVolume)}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {putPercentage}%
-
-
-
-
-
-
-
-
-
-
- OTM Ratio
-
- Volume in %
-
-
-
-
-
-
-
-
-
- =1 ? 0 : 100-(displayOTMRatio*100)?.toFixed(2)}>
-
-
-
-
- {(displayOTMRatio*100)?.toFixed(0)}%
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Time
- Date
- Expiry
- Strike
- C/P
- Sent.
- Spot
- Price
- Prem.
- Type
- Vol.
- OI
-
-
-
- {#each (data?.user?.tier === 'Pro' ? optionList : optionList?.slice(0,3)) as item, index}
-
-
-
-
- {formatTime(item?.time)}
-
-
-
- {formatDate(item?.date)}
-
-
-
- {item?.dte < 0 ? 'expired' : item?.dte +'d'}
-
-
-
- {item?.strike_price}
-
-
-
- {item?.put_call}
-
-
-
- {item?.sentiment}
-
-
-
- {item?.underlying_price}
-
-
-
- {item?.price}
-
-
-
- {abbreviateNumber(item?.cost_basis)}
-
-
-
- {item?.type}
-
-
-
-
-
- {new Intl.NumberFormat("en", {
- minimumFractionDigits: 0,
- maximumFractionDigits: 0
- }).format(item?.volume)}
-
-
-
{new Intl.NumberFormat("en", {
minimumFractionDigits: 0,
maximumFractionDigits: 0
- }).format(item?.open_interest)}
-
-
-
-
-
-
-
-
- {/each}
-
-
-
-
-
-
-
-
- {:else}
-
-
-
- No Options activity found
+ }).format(displayCallVolume)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {callPercentage}%
+
+
+
-
- {/if}
-
- {/if}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/routes/etf/[tickerID]/options/+page.ts b/src/routes/etf/[tickerID]/options/+page.ts
index 800bda47..2cad2a5f 100644
--- a/src/routes/etf/[tickerID]/options/+page.ts
+++ b/src/routes/etf/[tickerID]/options/+page.ts
@@ -15,16 +15,17 @@ function daysLeft(targetDate) {
export const load = async ({ parent, params }) => {
+
const {apiKey, apiURL} = await parent();
+
const getOptionsPlotData = async () => {
- let res;
const cachedData = getCache(params.tickerID, 'getOptionsPlotData');
if (cachedData) {
- res = cachedData;
+ return cachedData;
} else {
-
+
const postData = {
ticker: params.tickerID
};
@@ -38,43 +39,12 @@ export const load = async ({ parent, params }) => {
});
const output = await response.json();
-
- const totalCallVolume = output?.reduce((acc, obj) => acc + obj?.CALL?.volume, 0);
- const totalPutVolume = output?.reduce((acc, obj) => acc + obj?.PUT?.volume, 0);
- const putCallRatio = (totalPutVolume/totalCallVolume)?.toFixed(2);
-
- const totalVolume = output?.reduce((acc, obj) => {
- // Summing volume from both CALL and PUT
- return acc + obj?.CALL?.volume + obj?.PUT?.volume;
- }, 0);
- const totalOpenInterest = output?.reduce((acc, obj) => {
- // Summing volume from both CALL and PUT
- return acc + obj?.CALL?.open_interest + obj?.PUT?.open_interest;
- }, 0);
-
-
- // Summing the total open interest of CALL and PUT options
- const totalCallOpenInterest = output?.reduce((acc, obj) => acc + obj?.CALL.open_interest, 0);
- const totalPutOpenInterest = output?.reduce((acc, obj) => acc + obj?.PUT.open_interest, 0);
-
- // Computing the put-call ratio for open interest
- const putCallOpenInterestRatio = (totalPutOpenInterest / totalCallOpenInterest)?.toFixed(2);
-
- //Plot Data
- const dateList = output?.map(item => item.date);
- const callVolumeList = output?.map(item => item?.CALL?.volume);
- const putVolumeList = output?.map(item => item?.PUT?.volume);
- const callOpenInterestList = output?.map(item => item?.CALL?.open_interest);
- const putOpenInterestList = output?.map(item => item?.PUT?.open_interest);
-
- res = {plot: output, 'dateList': dateList, 'callOpenInterestList': callOpenInterestList, 'putOpenInterestList': putOpenInterestList, 'callVolumeList': callVolumeList, 'putVolumeList': putVolumeList, 'putCallRatio': putCallRatio, 'putCallOpenInterestRatio': putCallOpenInterestRatio,'totalVolume': totalVolume, 'totalOpenInterest': totalOpenInterest };
- setCache(params.tickerID, res, 'getOptionsPlotData');
+ setCache(params.tickerID, output, 'getOptionsPlotData');
+ return output;
}
- return res;
-
};
const getOptionsFlowData = async () => {
diff --git a/src/routes/stocks/[tickerID]/options/+page.svelte b/src/routes/stocks/[tickerID]/options/+page.svelte
index 7bc4852a..21e73a6f 100644
--- a/src/routes/stocks/[tickerID]/options/+page.svelte
+++ b/src/routes/stocks/[tickerID]/options/+page.svelte
@@ -15,6 +15,8 @@
export let data;
+ let rawPlotData = data?.getOptionsPlotData;
+ let filteredList = [];
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
let optionsPlotData = data?.getOptionsPlotData?.plot;
@@ -30,29 +32,29 @@
let latestPutCallRatio;
let displayOTMRatio;
- const totalPutCallRatio = data?.getOptionsPlotData?.putCallRatio;
- const totalVolume = data?.getOptionsPlotData?.totalVolume;
+ let totalVolume //= data?.getOptionsPlotData?.totalVolume;
- const totalOpenInterest = data?.getOptionsPlotData?.totalOpenInterest;
+ let totalOpenInterest //= data?.getOptionsPlotData?.totalOpenInterest;
// Computing the put-call ratio for open interest
- const putCallOpenInterestRatio = data?.getOptionsPlotData?.putCallOpenInterestRatio;
-
- const displayTotalVolume = new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0})?.format(totalVolume);
- const displayTotalOpenInterest = new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0})?.format(totalOpenInterest);
-
- const dateList = data?.getOptionsPlotData?.dateList;
-
- const callVolumeList = data?.getOptionsPlotData?.callVolumeList;
- const putVolumeList = data?.getOptionsPlotData?.putVolumeList;
- const callOpenInterestList = data?.getOptionsPlotData?.callOpenInterestList;
- const putOpenInterestList = data?.getOptionsPlotData?.putOpenInterestList;
+ let putCallOpenInterestRatio //= data?.getOptionsPlotData?.putCallOpenInterestRatio;
+ let putCallRatio;
+ let displayTotalVolume //= new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0})?.format(totalVolume);
+ let displayTotalOpenInterest //= new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0})?.format(totalOpenInterest);
+ let displayTotalPutCall
+ let dateList //= data?.getOptionsPlotData?.dateList;
+ let callVolumeList //= data?.getOptionsPlotData?.callVolumeList;
+ let putVolumeList //= data?.getOptionsPlotData?.putVolumeList;
+ let callOpenInterestList //= data?.getOptionsPlotData?.callOpenInterestList;
+ let putOpenInterestList //= data?.getOptionsPlotData?.putOpenInterestList;
+ let displayTimePeriod = 'threeMonths'
+
function formatDate(dateStr) {
// Parse the input date string (YYYY-mm-dd)
@@ -96,6 +98,11 @@
displayData = event.target.value;
}
+ function changeTimePeriod(event)
+ {
+ displayTimePeriod = event.target.value;
+ }
+
function plotData(callData, putData) {
@@ -220,7 +227,74 @@
// Calculate OTM/ITM ratio
displayOTMRatio = otmVolume / (itmVolume+otmVolume) ?? 0;
}
-
+
+function filterDate(filteredList, displayTimePeriod) {
+ const now = Date.now();
+ let cutoffDate;
+
+ switch (displayTimePeriod) {
+ case 'oneWeek':
+ cutoffDate = now - 7 * 24 * 60 * 60 * 1000;
+ break;
+ case 'oneMonth':
+ cutoffDate = now - 30 * 24 * 60 * 60 * 1000;
+ break;
+ case 'threeMonths':
+ cutoffDate = now - 90 * 24 * 60 * 60 * 1000;
+ break;
+ case 'sixMonths':
+ cutoffDate = now - 180 * 24 * 60 * 60 * 1000;
+ break;
+ case 'oneYear':
+ cutoffDate = now - 365 * 24 * 60 * 60 * 1000;
+ break;
+ default:
+ throw new Error('Invalid time period');
+ }
+
+ return filteredList?.filter(item => {
+ // Convert YYYY-MM-DD to a timestamp
+ const [year, month, day] = item?.date?.split('-')?.map(Number);
+ const itemTimestamp = new Date(year, month - 1, day)?.getTime();
+
+ return itemTimestamp >= cutoffDate;
+ });
+}
+
+
+function processPlotData(filteredList: any[]) {
+ const totals = filteredList?.reduce((acc, obj) => {
+ acc.callVolume += obj?.CALL?.volume;
+ acc.putVolume += obj?.PUT?.volume;
+ acc.callOpenInterest += obj?.CALL?.open_interest;
+ acc.putOpenInterest += obj?.PUT?.open_interest;
+ return acc;
+ }, { callVolume: 0, putVolume: 0, callOpenInterest: 0, putOpenInterest: 0 });
+
+ putCallRatio = (totals.putVolume / totals.callVolume)?.toFixed(2);
+ totalVolume = totals.callVolume + totals.putVolume;
+ totalOpenInterest = totals.callOpenInterest + totals.putOpenInterest;
+ putCallOpenInterestRatio = (totals.putOpenInterest / totals.callOpenInterest)?.toFixed(2);
+
+ dateList = filteredList?.map(item => item.date);
+ callVolumeList = filteredList?.map(item => item?.CALL?.volume);
+ putVolumeList = filteredList?.map(item => item?.PUT?.volume);
+ callOpenInterestList = filteredList?.map(item => item?.CALL?.open_interest);
+ putOpenInterestList = filteredList?.map(item => item?.PUT?.open_interest);
+
+ displayTotalVolume = new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0}).format(totalVolume);
+ displayTotalPutCall = new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0}).format(putCallRatio);
+ displayTotalOpenInterest = new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0}).format(totalOpenInterest);
+
+ // Determine the type of plot data to generate based on displayData
+ if (displayData === 'volume') {
+ options = plotData(callVolumeList, putVolumeList);
+ } else if (displayData === 'openInterest') {
+ options = plotData(callOpenInterestList, putOpenInterestList);
+ }
+
+}
+
async function handleScroll() {
const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
@@ -233,35 +307,36 @@
- onMount(async () => {
- calculateStats();
-
- if(data?.user?.tier === 'Pro') {
- window.addEventListener('scroll', handleScroll);
- return () => {
- window.removeEventListener('scroll', handleScroll);
- };
- }
- })
+onMount(async () => {
+ calculateStats();
+
+ if(data?.user?.tier === 'Pro') {
+ window.addEventListener('scroll', handleScroll);
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ };
+ }
+})
- $: {
- if(displayData && optionsPlotData?.length !== 0 && typeof window !== 'undefined') {
- if (displayData === 'volume') {
- options = plotData(callVolumeList, putVolumeList)
- }
- else if (displayData === 'openInterest') {
- options = plotData(callOpenInterestList, putOpenInterestList)
- }
- }
- }
+$: {
+ if ((displayTimePeriod || displayData) && optionsPlotData?.length !== 0 && typeof window !== 'undefined') {
+ // Filter the raw plot data based on the selected time period
+ filteredList = filterDate(rawPlotData, displayTimePeriod);
+ // Process the filtered list to generate the plot data
+ processPlotData(filteredList);
+ }
+}
+
+
+
-
+
@@ -300,7 +375,7 @@
{#if optionsPlotData?.length !== 0}
- Last 3 months of options activity involving {$displayCompanyName} by major institutional traders and hedge funds.
+ 1 Year of options activity involving {$displayCompanyName} by major institutional traders and hedge funds.
{:else}
There's no data available, indicating that major traders may not be actively betting on {$displayCompanyName}.
{/if}
@@ -311,90 +386,126 @@
{#if optionsPlotData?.length !== 0}
-
-
-
-
-
-
-
-
- Total Volume
-
-
-
-
{displayTotalVolume}
-
-
-
-
-
-
-
- Total OI
-
-
-
-
-
{displayTotalOpenInterest}
-
-
-
-
-
- P/C Ratio
-
-
-
-
- {totalPutCallRatio !== 'Infinity' ? totalPutCallRatio : '> 1'}
-
-
-
-
-
-
- OI P/C Ratio
-
-
-
-
{putCallOpenInterestRatio !== 'Infinity' ? putCallOpenInterestRatio : '> 1'}
-
-
-
+
+
+
+ Total Volume
+
+
+
+
+
+
+
+
+
+
+ {displayTotalVolume}
+
+
+
+
+ Total OI
+
+
+
+
+
+
+
+
+
+
+ {displayTotalOpenInterest}
+
+
+
+
+ P/C Ratio
+
+
+
+
+
+
+
+
+
+
+ {putCallRatio !== 'Infinity' ? putCallRatio : '> 1'}
+
+
+
+
+ OI P/C Ratio
+
+
+
+
+
+
+
+
+
+
+ {putCallOpenInterestRatio !== 'Infinity' ? putCallOpenInterestRatio : '> 1'}
+
+
-
-
-
-
-
-
- Choose a category
- Volume
- Open Interest
+
+
+
+ Choose a time period
+ 1 Week
+ 1 Month
+ 3 Months
+ 6 Months
+ 1 Year
+
+
+ Choose a category
+ Volume
+ Open Interest
+
+
+
+
-
+ {#if filteredList?.length !== 0}
+
+ {:else}
+
+
+
+ No Options activity found
+
+
+ {/if}
@@ -567,7 +678,7 @@
-
+
{formatTime(item?.time)}
@@ -583,11 +694,11 @@
{item?.strike_price}
-
+
{item?.put_call}
-
+
{item?.sentiment}
diff --git a/src/routes/stocks/[tickerID]/options/+page.ts b/src/routes/stocks/[tickerID]/options/+page.ts
index 21cd28c1..2cad2a5f 100644
--- a/src/routes/stocks/[tickerID]/options/+page.ts
+++ b/src/routes/stocks/[tickerID]/options/+page.ts
@@ -20,11 +20,10 @@ export const load = async ({ parent, params }) => {
const getOptionsPlotData = async () => {
- let res;
const cachedData = getCache(params.tickerID, 'getOptionsPlotData');
if (cachedData) {
- res = cachedData;
+ return cachedData;
} else {
const postData = {
@@ -40,43 +39,12 @@ export const load = async ({ parent, params }) => {
});
const output = await response.json();
-
- const totalCallVolume = output?.reduce((acc, obj) => acc + obj?.CALL?.volume, 0);
- const totalPutVolume = output?.reduce((acc, obj) => acc + obj?.PUT?.volume, 0);
- const putCallRatio = (totalPutVolume/totalCallVolume)?.toFixed(2);
-
- const totalVolume = output?.reduce((acc, obj) => {
- // Summing volume from both CALL and PUT
- return acc + obj?.CALL?.volume + obj?.PUT?.volume;
- }, 0);
- const totalOpenInterest = output?.reduce((acc, obj) => {
- // Summing volume from both CALL and PUT
- return acc + obj?.CALL?.open_interest + obj?.PUT?.open_interest;
- }, 0);
-
-
- // Summing the total open interest of CALL and PUT options
- const totalCallOpenInterest = output?.reduce((acc, obj) => acc + obj?.CALL.open_interest, 0);
- const totalPutOpenInterest = output?.reduce((acc, obj) => acc + obj?.PUT.open_interest, 0);
-
- // Computing the put-call ratio for open interest
- const putCallOpenInterestRatio = (totalPutOpenInterest / totalCallOpenInterest)?.toFixed(2);
-
- //Plot Data
- const dateList = output?.map(item => item.date);
- const callVolumeList = output?.map(item => item?.CALL?.volume);
- const putVolumeList = output?.map(item => item?.PUT?.volume);
- const callOpenInterestList = output?.map(item => item?.CALL?.open_interest);
- const putOpenInterestList = output?.map(item => item?.PUT?.open_interest);
-
- res = {plot: output, 'dateList': dateList, 'callOpenInterestList': callOpenInterestList, 'putOpenInterestList': putOpenInterestList, 'callVolumeList': callVolumeList, 'putVolumeList': putVolumeList, 'putCallRatio': putCallRatio, 'putCallOpenInterestRatio': putCallOpenInterestRatio,'totalVolume': totalVolume, 'totalOpenInterest': totalOpenInterest };
- setCache(params.tickerID, res, 'getOptionsPlotData');
+ setCache(params.tickerID, output, 'getOptionsPlotData');
+ return output;
}
- return res;
-
};
const getOptionsFlowData = async () => {