add tooltip to graphs
This commit is contained in:
parent
214b98eb67
commit
e2d8934fe7
@ -127,6 +127,7 @@ function findLowestAndHighestFee(data, lastDateStr) {
|
|||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
|
name: 'Available Shares',
|
||||||
data: availableList,
|
data: availableList,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
@ -135,6 +136,7 @@ function findLowestAndHighestFee(data, lastDateStr) {
|
|||||||
showSymbol: false
|
showSymbol: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: 'Fee [%]',
|
||||||
data: feeList,
|
data: feeList,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
areaStyle: {opacity: 1},
|
areaStyle: {opacity: 1},
|
||||||
|
|||||||
@ -94,7 +94,7 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="circle"
|
class="circle"
|
||||||
style="left:{d.x}px;top:{d.y}px;width:{d.r * ballSize}px;height:{d.r * ballSize}px;background-color:{(index === 1 && d.data.id === 'puts') ? '#FF2F1F' : (index === 1 && d.data.id === 'calls') ? '#0FB307' : '#1E1E1E'}; border: 0px solid #000;"
|
style="left:{d.x}px;top:{d.y}px;width:{d.r * ballSize}px;height:{d.r * ballSize}px;background-color:{(index === 1 && d.data.id === 'puts') ? '#FF2F1F' : (index === 1 && d.data.id === 'calls') ? '#37C97D' : '#1E1E1E'}; border: 0px solid #000;"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="text-group"
|
class="text-group"
|
||||||
|
|||||||
@ -110,6 +110,7 @@ function getPlotOptions() {
|
|||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
|
name: 'Total Volume',
|
||||||
data: totalVolumeList,
|
data: totalVolumeList,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
@ -118,12 +119,12 @@ function getPlotOptions() {
|
|||||||
showSymbol: false
|
showSymbol: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: 'Short Volume',
|
||||||
data: shortVolumeList,
|
data: shortVolumeList,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
areaStyle: {opacity: 1},
|
areaStyle: {opacity: 1},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#3B82F6' // Change bar color to white
|
color: '#E11D48' // Change bar color to white
|
||||||
},
|
},
|
||||||
showSymbol: false
|
showSymbol: false
|
||||||
},
|
},
|
||||||
@ -232,7 +233,7 @@ $: {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col sm:flex-row items-center ml-3 sm:ml-0 w-1/2 justify-center">
|
<div class="flex flex-col sm:flex-row items-center ml-3 sm:ml-0 w-1/2 justify-center">
|
||||||
<div class="h-full transform -translate-x-1/2 " aria-hidden="true"></div>
|
<div class="h-full transform -translate-x-1/2 " aria-hidden="true"></div>
|
||||||
<div class="w-3 h-3 bg-[#536FC5] border-4 box-content border-[#27272A] rounded-full transform sm:-translate-x-1/2" aria-hidden="true"></div>
|
<div class="w-3 h-3 bg-[#E11D48] border-4 box-content border-[#27272A] rounded-full transform sm:-translate-x-1/2" aria-hidden="true"></div>
|
||||||
<span class="mt-2 sm:mt-0 text-white text-xs sm:text-md sm:font-medium inline-block">
|
<span class="mt-2 sm:mt-0 text-white text-xs sm:text-md sm:font-medium inline-block">
|
||||||
Short Volume
|
Short Volume
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -6,14 +6,13 @@
|
|||||||
import { BarChart } from 'echarts/charts'
|
import { BarChart } from 'echarts/charts'
|
||||||
import { GridComponent, TooltipComponent } from 'echarts/components'
|
import { GridComponent, TooltipComponent } from 'echarts/components'
|
||||||
import { CanvasRenderer } from 'echarts/renderers'
|
import { CanvasRenderer } from 'echarts/renderers'
|
||||||
|
import { monthNames} from '$lib/utils';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
use([BarChart, GridComponent, TooltipComponent, CanvasRenderer])
|
use([BarChart, GridComponent, TooltipComponent, CanvasRenderer])
|
||||||
|
|
||||||
|
|
||||||
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
||||||
|
|
||||||
let isLoaded = false;
|
let isLoaded = false;
|
||||||
|
|
||||||
|
|
||||||
@ -22,25 +21,6 @@
|
|||||||
let sentiment;
|
let sentiment;
|
||||||
|
|
||||||
|
|
||||||
function normalizer(value) {
|
|
||||||
if (Math?.abs(value) >= 1e18) {
|
|
||||||
return { unit: 'Q', denominator: 1e18 };
|
|
||||||
} else if (Math?.abs(value) >= 1e12) {
|
|
||||||
return { unit: 'T', denominator: 1e12 };
|
|
||||||
} else if (Math?.abs(value) >= 1e9) {
|
|
||||||
return { unit: 'B', denominator: 1e9 };
|
|
||||||
} else if (Math?.abs(value) >= 1e6) {
|
|
||||||
return { unit: 'M', denominator: 1e6 };
|
|
||||||
} else if (Math?.abs(value) >= 1e5) {
|
|
||||||
return { unit: 'K', denominator: 1e5 };
|
|
||||||
} else if (Math?.abs(value) >= 1e4) {
|
|
||||||
return { unit: 'K', denominator: 1e4 };
|
|
||||||
} else {
|
|
||||||
return { unit: '', denominator: 1 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getPlotOptions() {
|
function getPlotOptions() {
|
||||||
let dates = [];
|
let dates = [];
|
||||||
let priceList = [];
|
let priceList = [];
|
||||||
@ -59,7 +39,6 @@
|
|||||||
|
|
||||||
sentiment = netCallList?.slice(-1)?.at(0) > netPutList?.slice(-1)?.at(0) ? 'bullish' : 'bearish';
|
sentiment = netCallList?.slice(-1)?.at(0) > netPutList?.slice(-1)?.at(0) ? 'bullish' : 'bearish';
|
||||||
|
|
||||||
const {unit, denominator } = normalizer(Math.max(...netCallList) ?? 0)
|
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -69,8 +48,8 @@
|
|||||||
},
|
},
|
||||||
animation: false,
|
animation: false,
|
||||||
grid: {
|
grid: {
|
||||||
left: '1%',
|
left: '3%',
|
||||||
right: '2%',
|
right: '3%',
|
||||||
bottom: '0%',
|
bottom: '0%',
|
||||||
top: '10%',
|
top: '10%',
|
||||||
containLabel: true
|
containLabel: true
|
||||||
@ -100,18 +79,10 @@
|
|||||||
splitLine: {
|
splitLine: {
|
||||||
show: false, // Disable x-axis grid lines
|
show: false, // Disable x-axis grid lines
|
||||||
},
|
},
|
||||||
|
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: '#fff', // Change label color to white
|
show: false // Hide y-axis labels
|
||||||
formatter: function (value, index) {
|
|
||||||
// Display every second tick
|
|
||||||
if (index % 2 === 0) {
|
|
||||||
//value = Math.max(value, 0);
|
|
||||||
return '$'+(value / denominator)?.toFixed(0) + unit; // Format value in millions
|
|
||||||
} else {
|
|
||||||
return ''; // Hide this tick
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
],
|
],
|
||||||
@ -254,7 +225,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{:else}
|
{:else}
|
||||||
|
|||||||
@ -1,115 +1,80 @@
|
|||||||
<script lang ='ts'>
|
<script lang="ts">
|
||||||
import { abbreviateNumber } from "$lib/utils";
|
import { abbreviateNumber } from "$lib/utils";
|
||||||
|
import { swapComponent, stockTicker, screenWidth, getCache, setCache } from '$lib/store';
|
||||||
import { swapComponent, stockTicker, screenWidth, getCache, setCache} from '$lib/store';
|
|
||||||
import InfoModal from '$lib/components/InfoModal.svelte';
|
import InfoModal from '$lib/components/InfoModal.svelte';
|
||||||
import { Chart } from 'svelte-echarts'
|
import { Chart } from 'svelte-echarts';
|
||||||
|
import { init, use } from 'echarts/core';
|
||||||
import { init, use } from 'echarts/core'
|
import { ScatterChart } from 'echarts/charts';
|
||||||
import { BarChart } from 'echarts/charts'
|
import { GridComponent, TooltipComponent } from 'echarts/components';
|
||||||
import { GridComponent, TooltipComponent } from 'echarts/components'
|
|
||||||
import { CanvasRenderer } from 'echarts/renderers';
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
export let data;
|
export let data: any; // Add type for `data` if possible
|
||||||
|
|
||||||
use([BarChart, GridComponent, TooltipComponent, CanvasRenderer])
|
use([ScatterChart, GridComponent, TooltipComponent, CanvasRenderer]);
|
||||||
|
|
||||||
let isLoaded = false;
|
let isLoaded = false;
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{ title: "Effective Date" },
|
||||||
title: "Effective Date",
|
{ title: "Expiration Date" },
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Expiration Date",
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let activeIdx = 0;
|
let activeIdx = 0;
|
||||||
|
|
||||||
|
function changeTab(index: number) {
|
||||||
function changeTab(index) {
|
|
||||||
activeIdx = index;
|
activeIdx = index;
|
||||||
optionsData = getPlotOptions(activeIdx === 0 ? 'effectiveDate' : 'expirationDate');
|
optionsData = getPlotOptions(activeIdx === 0 ? 'effectiveDate' : 'expirationDate');
|
||||||
}
|
}
|
||||||
|
|
||||||
let rawData = [];
|
let rawData: any[] = [];
|
||||||
let optionsData;
|
let optionsData: any;
|
||||||
let avgNotionalAmount;
|
let avgNotionalAmount: number | undefined;
|
||||||
let avgNotionalQuantity;
|
let avgNotionalQuantity: number | undefined;
|
||||||
|
|
||||||
|
|
||||||
function normalizer(value) {
|
function getPlotOptions(state: 'effectiveDate' | 'expirationDate') {
|
||||||
if (Math?.abs(value) >= 1e18) {
|
const combinedData = rawData?.map((item) => ({
|
||||||
return { unit: 'Q', denominator: 1e18 };
|
|
||||||
} else if (Math?.abs(value) >= 1e12) {
|
|
||||||
return { unit: 'T', denominator: 1e12 };
|
|
||||||
} else if (Math?.abs(value) >= 1e9) {
|
|
||||||
return { unit: 'B', denominator: 1e9 };
|
|
||||||
} else if (Math?.abs(value) >= 1e6) {
|
|
||||||
return { unit: 'M', denominator: 1e6 };
|
|
||||||
} else if (Math?.abs(value) >= 1e5) {
|
|
||||||
return { unit: 'K', denominator: 1e3 };
|
|
||||||
} else if (Math?.abs(value) >= 1e4) {
|
|
||||||
return { unit: 'K', denominator: 1e3 };
|
|
||||||
} else {
|
|
||||||
return { unit: '', denominator: 1 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getPlotOptions(state) {
|
|
||||||
|
|
||||||
const combinedData = rawData?.map(item => ({
|
|
||||||
date: state === 'effectiveDate' ? item['Effective Date'] : item['Expiration Date'],
|
date: state === 'effectiveDate' ? item['Effective Date'] : item['Expiration Date'],
|
||||||
notionalAmount: item['Notional amount-Leg 1'],
|
notionalAmount: item['Notional amount-Leg 1'],
|
||||||
notionalQuantity: item['Total notional quantity-Leg 1']
|
notionalQuantity: item['Total notional quantity-Leg 1'],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Group data by date and sum the values
|
// Group data by date and sum the values
|
||||||
const groupedData = combinedData.reduce((acc, curr) => {
|
const groupedData = combinedData.reduce((acc, curr) => {
|
||||||
const { date, notionalAmount, notionalQuantity } = curr;
|
const { date, notionalAmount, notionalQuantity } = curr;
|
||||||
|
|
||||||
// If the date already exists in the accumulator, sum up the values
|
|
||||||
if (acc[date]) {
|
if (acc[date]) {
|
||||||
acc[date].notionalAmount += notionalAmount;
|
acc[date].notionalAmount += notionalAmount;
|
||||||
acc[date].notionalQuantity += notionalQuantity;
|
acc[date].notionalQuantity += notionalQuantity;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, create a new entry for this date
|
|
||||||
acc[date] = {
|
acc[date] = {
|
||||||
date,
|
date,
|
||||||
notionalAmount,
|
notionalAmount,
|
||||||
notionalQuantity
|
notionalQuantity,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {} as Record<string, any>);
|
||||||
|
|
||||||
// Convert the grouped data back to an array
|
|
||||||
const result = Object.values(groupedData);
|
const result = Object.values(groupedData);
|
||||||
|
|
||||||
// Sort the result array based on the date
|
result?.sort((a, b) => new Date(a?.date).getTime() - new Date(b?.date).getTime());
|
||||||
result?.sort((a, b) => new Date(a?.date) - new Date(b?.date));
|
|
||||||
|
|
||||||
// Separate the sorted data back into individual arrays
|
const dates = result?.map((item) => item?.date);
|
||||||
const dates = result?.map(item => item?.date);
|
const notionalAmount = result?.map((item) => item?.notionalAmount);
|
||||||
const notionalAmount = result?.map(item => item?.notionalAmount);
|
const notionalQuantity = result?.map((item) => item?.notionalQuantity);
|
||||||
const notionalQuantity = result?.map(item => item?.notionalQuantity);
|
|
||||||
|
|
||||||
// Compute the average of item?.traded
|
|
||||||
const totalNotionalAmount = notionalAmount?.reduce((acc, item) => acc + item, 0);
|
const totalNotionalAmount = notionalAmount?.reduce((acc, item) => acc + item, 0);
|
||||||
avgNotionalAmount = totalNotionalAmount / notionalAmount?.length;
|
avgNotionalAmount = totalNotionalAmount / notionalAmount?.length;
|
||||||
|
|
||||||
const totalNotionalQuantity = notionalQuantity?.reduce((acc, item) => acc + item, 0);
|
const totalNotionalQuantity = notionalQuantity?.reduce((acc, item) => acc + item, 0);
|
||||||
avgNotionalQuantity = totalNotionalQuantity / notionalQuantity?.length;
|
avgNotionalQuantity = totalNotionalQuantity / notionalQuantity?.length;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
silent: true,
|
silent: true,
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
hideDelay: 100, // Set the delay in milliseconds
|
hideDelay: 100,
|
||||||
},
|
},
|
||||||
animation: false,
|
animation: false,
|
||||||
grid: {
|
grid: {
|
||||||
@ -117,79 +82,74 @@
|
|||||||
right: '3%',
|
right: '3%',
|
||||||
bottom: '0%',
|
bottom: '0%',
|
||||||
top: '10%',
|
top: '10%',
|
||||||
containLabel: true
|
containLabel: true,
|
||||||
},
|
},
|
||||||
xAxis:
|
xAxis: {
|
||||||
{
|
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
data: dates,
|
data: dates,
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
type: 'value',
|
type: 'value',
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false, // Disable x-axis grid lines
|
show: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: false // Hide y-axis labels
|
show: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'value',
|
type: 'value',
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false, // Disable x-axis grid lines
|
show: false,
|
||||||
},
|
},
|
||||||
position: 'right',
|
position: 'right',
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: false // Hide y-axis labels
|
show: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Notional Amount',
|
name: 'Notional Amount',
|
||||||
type: 'bar',
|
type: 'scatter',
|
||||||
data: notionalAmount,
|
data: dates?.map((date, index) => [date, notionalAmount[index]]),
|
||||||
barWidth: '50%',
|
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#8F54F4'
|
color: '#8F54F4',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Notional Quantity',
|
name: 'Notional Quantity',
|
||||||
type: 'bar',
|
type: 'scatter',
|
||||||
data: notionalQuantity,
|
data: dates?.map((date, index) => [date, notionalQuantity[index]]),
|
||||||
barWidth: '50%',
|
|
||||||
yAxisIndex: 1,
|
yAxisIndex: 1,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#FF9E21'
|
color: '#FF9E21',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSwapData(ticker) {
|
async function getSwapData(ticker: string) {
|
||||||
const cachedData = getCache(ticker, 'getSwapData');
|
const cachedData = getCache(ticker, 'getSwapData');
|
||||||
if (cachedData) {
|
if (cachedData) {
|
||||||
rawData = cachedData;
|
rawData = cachedData;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const postData = {ticker: ticker, path: 'swap-ticker'}
|
const postData = { ticker, path: 'swap-ticker' };
|
||||||
const response = await fetch('/api/ticker-data', {
|
const response = await fetch('/api/ticker-data', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify(postData)
|
body: JSON.stringify(postData),
|
||||||
});
|
});
|
||||||
if (!response.ok) throw new Error('API request failed');
|
if (!response.ok) throw new Error('API request failed');
|
||||||
rawData = await response.json();
|
rawData = await response.json();
|
||||||
@ -199,7 +159,7 @@
|
|||||||
rawData = [];
|
rawData = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$swapComponent = rawData?.length !== 0;
|
$swapComponent = rawData?.length !== 0; // Correct the use of `$`
|
||||||
}
|
}
|
||||||
|
|
||||||
$: if ($stockTicker && typeof window !== 'undefined') {
|
$: if ($stockTicker && typeof window !== 'undefined') {
|
||||||
@ -211,12 +171,10 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$: charNumber = $screenWidth < 640 ? 20 : 40;
|
$: charNumber = $screenWidth < 640 ? 20 : 40;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:options immutable={true} />
|
|
||||||
|
|
||||||
|
|
||||||
<section class="overflow-hidden text-white h-full pb-8">
|
<section class="overflow-hidden text-white h-full pb-8">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user