add otm ratio
This commit is contained in:
parent
539a4cb19b
commit
d54833f3e9
@ -1,70 +1,54 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import {numberOfUnreadNotification, displayCompanyName, etfTicker} from '$lib/store';
|
import {numberOfUnreadNotification, displayCompanyName, etfTicker} from '$lib/store';
|
||||||
import { Chart } from 'svelte-echarts'
|
import { Chart } from 'svelte-echarts'
|
||||||
import { abbreviateNumber } from '$lib/utils';
|
import { abbreviateNumber } from '$lib/utils';
|
||||||
import InfoModal from '$lib/components/InfoModal.svelte';
|
import InfoModal from '$lib/components/InfoModal.svelte';
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
import UpgradeToPro from '$lib/components/UpgradeToPro.svelte';
|
import UpgradeToPro from '$lib/components/UpgradeToPro.svelte';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||||
|
|
||||||
let optionsPlotData = data?.getOptionsPlotData?.plot;
|
let optionsPlotData = data?.getOptionsPlotData?.plot;
|
||||||
let displayData = 'volume';
|
let displayData = 'volume';
|
||||||
let options;
|
let options;
|
||||||
let rawData = data?.getOptionsFlowData
|
let rawData = data?.getOptionsFlowData
|
||||||
let optionList = rawData?.slice(0,30);
|
let optionList = rawData?.slice(0,30);
|
||||||
let flowSentiment = 'n/a';
|
let flowSentiment = 'n/a';
|
||||||
let callPercentage;
|
let callPercentage;
|
||||||
let putPercentage;
|
let putPercentage;
|
||||||
let displayCallVolume;
|
let displayCallVolume;
|
||||||
let displayPutVolume;
|
let displayPutVolume;
|
||||||
let latestPutCallRatio;
|
let latestPutCallRatio;
|
||||||
|
let displayOTMRatio;
|
||||||
|
|
||||||
const totalPutCallRatio = data?.getOptionsPlotData?.putCallRatio;
|
const totalPutCallRatio = data?.getOptionsPlotData?.putCallRatio;
|
||||||
|
|
||||||
|
|
||||||
const totalVolume = data?.getOptionsPlotData?.totalVolume;
|
const totalVolume = data?.getOptionsPlotData?.totalVolume;
|
||||||
|
|
||||||
const totalOpenInterest = data?.getOptionsPlotData?.totalOpenInterest;
|
const totalOpenInterest = data?.getOptionsPlotData?.totalOpenInterest;
|
||||||
|
|
||||||
|
|
||||||
// Computing the put-call ratio for open interest
|
// Computing the put-call ratio for open interest
|
||||||
const putCallOpenInterestRatio = data?.getOptionsPlotData?.putCallOpenInterestRatio;
|
const putCallOpenInterestRatio = data?.getOptionsPlotData?.putCallOpenInterestRatio;
|
||||||
|
|
||||||
const displayTotalVolume = new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0})?.format(totalVolume);
|
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 displayTotalOpenInterest = new Intl.NumberFormat("en", {minimumFractionDigits: 0, maximumFractionDigits: 0})?.format(totalOpenInterest);
|
||||||
|
|
||||||
const dateList = data?.getOptionsPlotData?.dateList;
|
const dateList = data?.getOptionsPlotData?.dateList;
|
||||||
|
|
||||||
const callVolumeList = data?.getOptionsPlotData?.callVolumeList;
|
const callVolumeList = data?.getOptionsPlotData?.callVolumeList;
|
||||||
const putVolumeList = data?.getOptionsPlotData?.putVolumeList;
|
const putVolumeList = data?.getOptionsPlotData?.putVolumeList;
|
||||||
const callOpenInterestList = data?.getOptionsPlotData?.callOpenInterestList;
|
const callOpenInterestList = data?.getOptionsPlotData?.callOpenInterestList;
|
||||||
const putOpenInterestList = data?.getOptionsPlotData?.putOpenInterestList;
|
const putOpenInterestList = data?.getOptionsPlotData?.putOpenInterestList;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function formatTime(timeString) {
|
function formatDate(dateStr) {
|
||||||
// Split the time string into components
|
|
||||||
const [hours, minutes, seconds] = timeString.split(':').map(Number);
|
|
||||||
|
|
||||||
// Determine AM or PM
|
|
||||||
const period = hours >= 12 ? 'PM' : 'AM';
|
|
||||||
|
|
||||||
// Convert hours from 24-hour to 12-hour format
|
|
||||||
const formattedHours = hours % 12 || 12; // Converts 0 to 12 for midnight
|
|
||||||
|
|
||||||
// Format the time string
|
|
||||||
const formattedTimeString = `${formattedHours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')} ${period}`;
|
|
||||||
|
|
||||||
return formattedTimeString;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function formatDate(dateStr) {
|
|
||||||
// Parse the input date string (YYYY-mm-dd)
|
// Parse the input date string (YYYY-mm-dd)
|
||||||
var date = new Date(dateStr);
|
var date = new Date(dateStr);
|
||||||
|
|
||||||
@ -83,22 +67,32 @@ function formatDate(dateStr) {
|
|||||||
var formattedDate = month + "/" + day + "/" + year;
|
var formattedDate = month + "/" + day + "/" + year;
|
||||||
|
|
||||||
return formattedDate;
|
return formattedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatTime(timeString) {
|
||||||
|
// Split the time string into components
|
||||||
|
const [hours, minutes, seconds] = timeString.split(':').map(Number);
|
||||||
|
|
||||||
|
// Determine AM or PM
|
||||||
|
const period = hours >= 12 ? 'PM' : 'AM';
|
||||||
|
|
||||||
function changeStatement(event)
|
// Convert hours from 24-hour to 12-hour format
|
||||||
{
|
const formattedHours = hours % 12 || 12; // Converts 0 to 12 for midnight
|
||||||
|
|
||||||
|
// Format the time string
|
||||||
|
const formattedTimeString = `${formattedHours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')} ${period}`;
|
||||||
|
|
||||||
|
return formattedTimeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeStatement(event)
|
||||||
|
{
|
||||||
displayData = event.target.value;
|
displayData = event.target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tableVolume = 0;
|
|
||||||
let tableOpenInterest = 0;
|
|
||||||
let tableAvgDTE = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function plotData(callData, putData) {
|
function plotData(callData, putData) {
|
||||||
const options = {
|
const options = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
@ -168,16 +162,29 @@ function plotData(callData, putData) {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateStats() {
|
function calculateStats() {
|
||||||
const { callVolumeSum, putVolumeSum, bullishCount, bearishCount } = rawData?.reduce((acc, item) => {
|
const currentPrice = parseFloat(data?.getStockQuote?.price);
|
||||||
|
|
||||||
|
const { callVolumeSum, putVolumeSum, bullishCount, bearishCount, otmVolume, itmVolume } = rawData?.reduce((acc, item) => {
|
||||||
const volume = parseInt(item?.volume);
|
const volume = parseInt(item?.volume);
|
||||||
|
const strikePrice = parseFloat(item?.strike_price);
|
||||||
|
|
||||||
if (item?.put_call === "Calls") {
|
if (item?.put_call === "Calls") {
|
||||||
acc.callVolumeSum += volume;
|
acc.callVolumeSum += volume;
|
||||||
|
if (strikePrice > currentPrice) {
|
||||||
|
acc.otmVolume += volume;
|
||||||
|
} else {
|
||||||
|
acc.itmVolume += volume;
|
||||||
|
}
|
||||||
} else if (item?.put_call === "Puts") {
|
} else if (item?.put_call === "Puts") {
|
||||||
acc.putVolumeSum += volume;
|
acc.putVolumeSum += volume;
|
||||||
|
if (strikePrice < currentPrice) {
|
||||||
|
acc.itmVolume += volume;
|
||||||
|
} else {
|
||||||
|
acc.otmVolume += volume;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item?.sentiment === "Bullish") {
|
if (item?.sentiment === "Bullish") {
|
||||||
@ -187,27 +194,27 @@ function calculateStats() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, { callVolumeSum: 0, putVolumeSum: 0, bullishCount: 0, bearishCount: 0 });
|
}, { callVolumeSum: 0, putVolumeSum: 0, bullishCount: 0, bearishCount: 0, otmVolume: 0, itmVolume: 0 });
|
||||||
|
|
||||||
if(bullishCount > bearishCount) {
|
if (bullishCount > bearishCount) {
|
||||||
flowSentiment = 'Bullish'
|
flowSentiment = 'Bullish';
|
||||||
}
|
} else if (bullishCount < bearishCount) {
|
||||||
else if (bullishCount < bearishCount) {
|
flowSentiment = 'Bearish';
|
||||||
flowSentiment = 'Bearish'
|
|
||||||
} else {
|
} else {
|
||||||
flowSentiment = 'Neutral';
|
flowSentiment = 'Neutral';
|
||||||
}
|
}
|
||||||
latestPutCallRatio = (putVolumeSum/callVolumeSum);
|
|
||||||
|
|
||||||
callPercentage = Math.floor((callVolumeSum)/(callVolumeSum+putVolumeSum)*100);
|
|
||||||
putPercentage = (100-callPercentage);
|
|
||||||
|
|
||||||
|
latestPutCallRatio = (putVolumeSum / callVolumeSum);
|
||||||
|
callPercentage = Math.floor((callVolumeSum) / (callVolumeSum + putVolumeSum) * 100);
|
||||||
|
putPercentage = (100 - callPercentage);
|
||||||
displayCallVolume = callVolumeSum;
|
displayCallVolume = callVolumeSum;
|
||||||
displayPutVolume = putVolumeSum;
|
displayPutVolume = putVolumeSum;
|
||||||
|
|
||||||
}
|
// Calculate OTM/ITM ratio
|
||||||
|
displayOTMRatio = otmVolume / (itmVolume+otmVolume) ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
async function handleScroll() {
|
async function handleScroll() {
|
||||||
const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
|
const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
|
||||||
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
|
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
|
||||||
if (isBottom && optionList?.length !== rawData?.length) {
|
if (isBottom && optionList?.length !== rawData?.length) {
|
||||||
@ -219,8 +226,7 @@ async function handleScroll() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
|
||||||
calculateStats();
|
calculateStats();
|
||||||
|
|
||||||
if(data?.user?.tier === 'Pro') {
|
if(data?.user?.tier === 'Pro') {
|
||||||
@ -229,10 +235,10 @@ onMount(async () => {
|
|||||||
window.removeEventListener('scroll', handleScroll);
|
window.removeEventListener('scroll', handleScroll);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if(displayData && optionsPlotData?.length !== 0 && typeof window !== 'undefined') {
|
if(displayData && optionsPlotData?.length !== 0 && typeof window !== 'undefined') {
|
||||||
if (displayData === 'volume') {
|
if (displayData === 'volume') {
|
||||||
options = plotData(callVolumeList, putVolumeList)
|
options = plotData(callVolumeList, putVolumeList)
|
||||||
@ -241,36 +247,36 @@ $: {
|
|||||||
options = plotData(callOpenInterestList, putOpenInterestList)
|
options = plotData(callOpenInterestList, putOpenInterestList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<title>
|
<title>
|
||||||
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ''} {$displayCompanyName} ({$etfTicker}) Options Activity · stocknear
|
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ''} {$displayCompanyName} ({$etfTicker}) Options Activity · stocknear
|
||||||
</title>
|
</title>
|
||||||
<meta name="description" content={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$etfTicker}).`} />
|
<meta name="description" content={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$etfTicker}).`} />
|
||||||
|
|
||||||
<!-- Other meta tags -->
|
<!-- Other meta tags -->
|
||||||
<meta property="og:title" content={`${$displayCompanyName} (${$etfTicker}) Options Activity · stocknear`}/>
|
<meta property="og:title" content={`${$displayCompanyName} (${$etfTicker}) Options Activity · stocknear`}/>
|
||||||
<meta property="og:description" content={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$etfTicker}).`} />
|
<meta property="og:description" content={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$etfTicker}).`} />
|
||||||
<meta property="og:type" content="website"/>
|
<meta property="og:type" content="website"/>
|
||||||
<!-- Add more Open Graph meta tags as needed -->
|
<!-- Add more Open Graph meta tags as needed -->
|
||||||
|
|
||||||
<!-- Twitter specific meta tags -->
|
<!-- Twitter specific meta tags -->
|
||||||
<meta name="twitter:card" content="summary_large_image"/>
|
<meta name="twitter:card" content="summary_large_image"/>
|
||||||
<meta name="twitter:title" content={`${$displayCompanyName} (${$etfTicker}) Options Activity · stocknear`}/>
|
<meta name="twitter:title" content={`${$displayCompanyName} (${$etfTicker}) Options Activity · stocknear`}/>
|
||||||
<meta name="twitter:description" content={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$etfTicker}).`} />
|
<meta name="twitter:description" content={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$etfTicker}).`} />
|
||||||
<!-- Add more Twitter meta tags as needed -->
|
<!-- Add more Twitter meta tags as needed -->
|
||||||
|
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -400,7 +406,7 @@ $: {
|
|||||||
<!--Start Flow Sentiment-->
|
<!--Start Flow Sentiment-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Flow Sentiment</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Flow Sentiment</span>
|
||||||
<span class="text-start text-[1rem] font-medium {flowSentiment === 'Bullish' ? 'text-[#00FC50]' : 'text-[#FC2120]'}">{flowSentiment}</span>
|
<span class="text-start text-[1rem] font-medium {flowSentiment === 'Bullish' ? 'text-[#00FC50]' : 'text-[#FC2120]'}">{flowSentiment}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -409,7 +415,7 @@ $: {
|
|||||||
<!--Start Put/Call-->
|
<!--Start Put/Call-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Put/Call</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Put/Call</span>
|
||||||
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
{latestPutCallRatio?.toFixed(3)}
|
{latestPutCallRatio?.toFixed(3)}
|
||||||
</span>
|
</span>
|
||||||
@ -436,7 +442,7 @@ $: {
|
|||||||
<!--Start Call Flow-->
|
<!--Start Call Flow-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Call Flow</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Call Flow</span>
|
||||||
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
{new Intl.NumberFormat("en", {
|
{new Intl.NumberFormat("en", {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
@ -465,7 +471,7 @@ $: {
|
|||||||
<!--Start Put Flow-->
|
<!--Start Put Flow-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Put Flow</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Put Flow</span>
|
||||||
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
{new Intl.NumberFormat("en", {
|
{new Intl.NumberFormat("en", {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
@ -493,6 +499,34 @@ $: {
|
|||||||
</div>
|
</div>
|
||||||
<!--End Put Flow-->
|
<!--End Put Flow-->
|
||||||
|
|
||||||
|
<!--Start Put/Call-->
|
||||||
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
|
<div class="flex flex-col items-start">
|
||||||
|
<span class="font-medium text-gray-200 text-[1rem] ">Ratio %</span>
|
||||||
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
|
OTM / ITM
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- Circular Progress -->
|
||||||
|
<div class="relative size-14 ml-auto">
|
||||||
|
<svg class="size-full w-14 h-14" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- Background Circle -->
|
||||||
|
<circle cx="18" cy="18" r="16" fill="none" class="stroke-current text-[#3E3E3E]" stroke-width="3"></circle>
|
||||||
|
<!-- Progress Circle inside a group with rotation -->
|
||||||
|
<g class="origin-center -rotate-90 transform">
|
||||||
|
<circle cx="18" cy="18" r="16" fill="none" class="stroke-current text-[#EE5365]" stroke-width="3" stroke-dasharray="100" stroke-dashoffset={displayOTMRatio >=1 ? 0 : 100-(displayOTMRatio*100)?.toFixed(2)}></circle>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<!-- Percentage Text -->
|
||||||
|
<div class="absolute top-1/2 start-1/2 transform -translate-y-1/2 -translate-x-1/2">
|
||||||
|
<span class="text-center text-white text-sm">{(displayOTMRatio*100)?.toFixed(0)}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Circular Progress -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!--End Put/Call-->
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -530,7 +564,7 @@ $: {
|
|||||||
{formatTime(item?.time)}
|
{formatTime(item?.time)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="text-white text-xs sm:text-sm text-start whitespace-nowrap">
|
<td class="text-white text-xs sm:text-sm text-start">
|
||||||
{formatDate(item?.date)}
|
{formatDate(item?.date)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ let putPercentage;
|
|||||||
let displayCallVolume;
|
let displayCallVolume;
|
||||||
let displayPutVolume;
|
let displayPutVolume;
|
||||||
let latestPutCallRatio;
|
let latestPutCallRatio;
|
||||||
|
let displayOTMRatio;
|
||||||
|
|
||||||
const totalPutCallRatio = data?.getOptionsPlotData?.putCallRatio;
|
const totalPutCallRatio = data?.getOptionsPlotData?.putCallRatio;
|
||||||
|
|
||||||
@ -89,10 +90,6 @@ function changeStatement(event)
|
|||||||
displayData = event.target.value;
|
displayData = event.target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tableVolume = 0;
|
|
||||||
let tableOpenInterest = 0;
|
|
||||||
let tableAvgDTE = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function plotData(callData, putData) {
|
function plotData(callData, putData) {
|
||||||
@ -168,13 +165,26 @@ function plotData(callData, putData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function calculateStats() {
|
function calculateStats() {
|
||||||
const { callVolumeSum, putVolumeSum, bullishCount, bearishCount } = rawData?.reduce((acc, item) => {
|
const currentPrice = parseFloat(data?.getStockQuote?.price);
|
||||||
|
|
||||||
|
const { callVolumeSum, putVolumeSum, bullishCount, bearishCount, otmVolume, itmVolume } = rawData?.reduce((acc, item) => {
|
||||||
const volume = parseInt(item?.volume);
|
const volume = parseInt(item?.volume);
|
||||||
|
const strikePrice = parseFloat(item?.strike_price);
|
||||||
|
|
||||||
if (item?.put_call === "Calls") {
|
if (item?.put_call === "Calls") {
|
||||||
acc.callVolumeSum += volume;
|
acc.callVolumeSum += volume;
|
||||||
|
if (strikePrice > currentPrice) {
|
||||||
|
acc.otmVolume += volume;
|
||||||
|
} else {
|
||||||
|
acc.itmVolume += volume;
|
||||||
|
}
|
||||||
} else if (item?.put_call === "Puts") {
|
} else if (item?.put_call === "Puts") {
|
||||||
acc.putVolumeSum += volume;
|
acc.putVolumeSum += volume;
|
||||||
|
if (strikePrice < currentPrice) {
|
||||||
|
acc.itmVolume += volume;
|
||||||
|
} else {
|
||||||
|
acc.otmVolume += volume;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item?.sentiment === "Bullish") {
|
if (item?.sentiment === "Bullish") {
|
||||||
@ -184,24 +194,24 @@ function calculateStats() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, { callVolumeSum: 0, putVolumeSum: 0, bullishCount: 0, bearishCount: 0 });
|
}, { callVolumeSum: 0, putVolumeSum: 0, bullishCount: 0, bearishCount: 0, otmVolume: 0, itmVolume: 0 });
|
||||||
|
|
||||||
if(bullishCount > bearishCount) {
|
if (bullishCount > bearishCount) {
|
||||||
flowSentiment = 'Bullish'
|
flowSentiment = 'Bullish';
|
||||||
}
|
} else if (bullishCount < bearishCount) {
|
||||||
else if (bullishCount < bearishCount) {
|
flowSentiment = 'Bearish';
|
||||||
flowSentiment = 'Bearish'
|
|
||||||
} else {
|
} else {
|
||||||
flowSentiment = 'Neutral';
|
flowSentiment = 'Neutral';
|
||||||
}
|
}
|
||||||
latestPutCallRatio = (putVolumeSum/callVolumeSum);
|
|
||||||
|
|
||||||
callPercentage = Math.floor((callVolumeSum)/(callVolumeSum+putVolumeSum)*100);
|
|
||||||
putPercentage = (100-callPercentage);
|
|
||||||
|
|
||||||
|
latestPutCallRatio = (putVolumeSum / callVolumeSum);
|
||||||
|
callPercentage = Math.floor((callVolumeSum) / (callVolumeSum + putVolumeSum) * 100);
|
||||||
|
putPercentage = (100 - callPercentage);
|
||||||
displayCallVolume = callVolumeSum;
|
displayCallVolume = callVolumeSum;
|
||||||
displayPutVolume = putVolumeSum;
|
displayPutVolume = putVolumeSum;
|
||||||
|
|
||||||
|
// Calculate OTM/ITM ratio
|
||||||
|
displayOTMRatio = otmVolume / (itmVolume+otmVolume) ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleScroll() {
|
async function handleScroll() {
|
||||||
@ -217,7 +227,6 @@ async function handleScroll() {
|
|||||||
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
|
||||||
calculateStats();
|
calculateStats();
|
||||||
|
|
||||||
if(data?.user?.tier === 'Pro') {
|
if(data?.user?.tier === 'Pro') {
|
||||||
@ -397,7 +406,7 @@ $: {
|
|||||||
<!--Start Flow Sentiment-->
|
<!--Start Flow Sentiment-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Flow Sentiment</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Flow Sentiment</span>
|
||||||
<span class="text-start text-[1rem] font-medium {flowSentiment === 'Bullish' ? 'text-[#00FC50]' : 'text-[#FC2120]'}">{flowSentiment}</span>
|
<span class="text-start text-[1rem] font-medium {flowSentiment === 'Bullish' ? 'text-[#00FC50]' : 'text-[#FC2120]'}">{flowSentiment}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -406,7 +415,7 @@ $: {
|
|||||||
<!--Start Put/Call-->
|
<!--Start Put/Call-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Put/Call</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Put/Call</span>
|
||||||
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
{latestPutCallRatio?.toFixed(3)}
|
{latestPutCallRatio?.toFixed(3)}
|
||||||
</span>
|
</span>
|
||||||
@ -433,7 +442,7 @@ $: {
|
|||||||
<!--Start Call Flow-->
|
<!--Start Call Flow-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Call Flow</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Call Flow</span>
|
||||||
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
{new Intl.NumberFormat("en", {
|
{new Intl.NumberFormat("en", {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
@ -462,7 +471,7 @@ $: {
|
|||||||
<!--Start Put Flow-->
|
<!--Start Put Flow-->
|
||||||
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<span class="font-medium text-gray-200 text-sm ">Put Flow</span>
|
<span class="font-medium text-gray-200 text-[1rem] ">Put Flow</span>
|
||||||
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
{new Intl.NumberFormat("en", {
|
{new Intl.NumberFormat("en", {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
@ -490,6 +499,34 @@ $: {
|
|||||||
</div>
|
</div>
|
||||||
<!--End Put Flow-->
|
<!--End Put Flow-->
|
||||||
|
|
||||||
|
<!--Start Put/Call-->
|
||||||
|
<div class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-[#262626] shadow-lg rounded-md h-20">
|
||||||
|
<div class="flex flex-col items-start">
|
||||||
|
<span class="font-medium text-gray-200 text-[1rem] ">Ratio %</span>
|
||||||
|
<span class="text-start text-sm sm:text-[1rem] font-medium text-white">
|
||||||
|
OTM / ITM
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- Circular Progress -->
|
||||||
|
<div class="relative size-14 ml-auto">
|
||||||
|
<svg class="size-full w-14 h-14" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- Background Circle -->
|
||||||
|
<circle cx="18" cy="18" r="16" fill="none" class="stroke-current text-[#3E3E3E]" stroke-width="3"></circle>
|
||||||
|
<!-- Progress Circle inside a group with rotation -->
|
||||||
|
<g class="origin-center -rotate-90 transform">
|
||||||
|
<circle cx="18" cy="18" r="16" fill="none" class="stroke-current text-[#EE5365]" stroke-width="3" stroke-dasharray="100" stroke-dashoffset={displayOTMRatio >=1 ? 0 : 100-(displayOTMRatio*100)?.toFixed(2)}></circle>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<!-- Percentage Text -->
|
||||||
|
<div class="absolute top-1/2 start-1/2 transform -translate-y-1/2 -translate-x-1/2">
|
||||||
|
<span class="text-center text-white text-sm">{(displayOTMRatio*100)?.toFixed(0)}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Circular Progress -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!--End Put/Call-->
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user