add tooltip to graphs
This commit is contained in:
parent
214b98eb67
commit
e2d8934fe7
@ -126,7 +126,8 @@ function findLowestAndHighestFee(data, lastDateStr) {
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
{
|
||||
name: 'Available Shares',
|
||||
data: availableList,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
@ -135,6 +136,7 @@ function findLowestAndHighestFee(data, lastDateStr) {
|
||||
showSymbol: false
|
||||
},
|
||||
{
|
||||
name: 'Fee [%]',
|
||||
data: feeList,
|
||||
type: 'line',
|
||||
areaStyle: {opacity: 1},
|
||||
|
||||
@ -94,7 +94,7 @@
|
||||
>
|
||||
<div
|
||||
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
|
||||
class="text-group"
|
||||
|
||||
@ -109,7 +109,8 @@ function getPlotOptions() {
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
{
|
||||
name: 'Total Volume',
|
||||
data: totalVolumeList,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
@ -118,12 +119,12 @@ function getPlotOptions() {
|
||||
showSymbol: false
|
||||
},
|
||||
{
|
||||
|
||||
name: 'Short Volume',
|
||||
data: shortVolumeList,
|
||||
type: 'line',
|
||||
areaStyle: {opacity: 1},
|
||||
itemStyle: {
|
||||
color: '#3B82F6' // Change bar color to white
|
||||
color: '#E11D48' // Change bar color to white
|
||||
},
|
||||
showSymbol: false
|
||||
},
|
||||
@ -232,7 +233,7 @@ $: {
|
||||
</div>
|
||||
<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="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">
|
||||
Short Volume
|
||||
</span>
|
||||
|
||||
@ -6,14 +6,13 @@
|
||||
import { BarChart } from 'echarts/charts'
|
||||
import { GridComponent, TooltipComponent } from 'echarts/components'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { monthNames} from '$lib/utils';
|
||||
|
||||
export let data;
|
||||
|
||||
use([BarChart, GridComponent, TooltipComponent, CanvasRenderer])
|
||||
|
||||
|
||||
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
|
||||
let isLoaded = false;
|
||||
|
||||
|
||||
@ -22,25 +21,6 @@
|
||||
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() {
|
||||
let dates = [];
|
||||
let priceList = [];
|
||||
@ -59,7 +39,6 @@
|
||||
|
||||
sentiment = netCallList?.slice(-1)?.at(0) > netPutList?.slice(-1)?.at(0) ? 'bullish' : 'bearish';
|
||||
|
||||
const {unit, denominator } = normalizer(Math.max(...netCallList) ?? 0)
|
||||
|
||||
const option = {
|
||||
silent: true,
|
||||
@ -69,8 +48,8 @@
|
||||
},
|
||||
animation: false,
|
||||
grid: {
|
||||
left: '1%',
|
||||
right: '2%',
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
bottom: '0%',
|
||||
top: '10%',
|
||||
containLabel: true
|
||||
@ -95,23 +74,15 @@
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
{
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: false, // Disable x-axis grid lines
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#fff', // Change label color to white
|
||||
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
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
axisLabel: {
|
||||
show: false // Hide y-axis labels
|
||||
}
|
||||
},
|
||||
|
||||
],
|
||||
@ -253,8 +224,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
{/if}
|
||||
|
||||
{:else}
|
||||
|
||||
@ -1,195 +1,155 @@
|
||||
<script lang ='ts'>
|
||||
<script lang="ts">
|
||||
import { abbreviateNumber } from "$lib/utils";
|
||||
import { swapComponent, stockTicker, screenWidth, getCache, setCache } from '$lib/store';
|
||||
import InfoModal from '$lib/components/InfoModal.svelte';
|
||||
import { Chart } from 'svelte-echarts';
|
||||
import { init, use } from 'echarts/core';
|
||||
import { ScatterChart } from 'echarts/charts';
|
||||
import { GridComponent, TooltipComponent } from 'echarts/components';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
export let data: any; // Add type for `data` if possible
|
||||
|
||||
import { swapComponent, stockTicker, screenWidth, getCache, setCache} from '$lib/store';
|
||||
import InfoModal from '$lib/components/InfoModal.svelte';
|
||||
import { Chart } from 'svelte-echarts'
|
||||
use([ScatterChart, GridComponent, TooltipComponent, CanvasRenderer]);
|
||||
|
||||
import { init, use } from 'echarts/core'
|
||||
import { BarChart } from 'echarts/charts'
|
||||
import { GridComponent, TooltipComponent } from 'echarts/components'
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
export let data;
|
||||
let isLoaded = false;
|
||||
|
||||
use([BarChart, GridComponent, TooltipComponent, CanvasRenderer])
|
||||
|
||||
let isLoaded = false;
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: "Effective Date",
|
||||
},
|
||||
{
|
||||
title: "Expiration Date",
|
||||
}
|
||||
const tabs = [
|
||||
{ title: "Effective Date" },
|
||||
{ title: "Expiration Date" },
|
||||
];
|
||||
|
||||
let activeIdx = 0;
|
||||
|
||||
|
||||
function changeTab(index) {
|
||||
function changeTab(index: number) {
|
||||
activeIdx = index;
|
||||
optionsData = getPlotOptions(activeIdx === 0 ? 'effectiveDate' : 'expirationDate');
|
||||
}
|
||||
|
||||
let rawData = [];
|
||||
let optionsData;
|
||||
let avgNotionalAmount;
|
||||
let avgNotionalQuantity;
|
||||
|
||||
let rawData: any[] = [];
|
||||
let optionsData: any;
|
||||
let avgNotionalAmount: number | undefined;
|
||||
let avgNotionalQuantity: number | undefined;
|
||||
|
||||
|
||||
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: 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 => ({
|
||||
function getPlotOptions(state: 'effectiveDate' | 'expirationDate') {
|
||||
const combinedData = rawData?.map((item) => ({
|
||||
date: state === 'effectiveDate' ? item['Effective Date'] : item['Expiration Date'],
|
||||
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
|
||||
const groupedData = combinedData.reduce((acc, curr) => {
|
||||
const { date, notionalAmount, notionalQuantity } = curr;
|
||||
|
||||
// If the date already exists in the accumulator, sum up the values
|
||||
if (acc[date]) {
|
||||
acc[date].notionalAmount += notionalAmount;
|
||||
acc[date].notionalQuantity += notionalQuantity;
|
||||
} else {
|
||||
// Otherwise, create a new entry for this date
|
||||
acc[date] = {
|
||||
date,
|
||||
notionalAmount,
|
||||
notionalQuantity
|
||||
notionalQuantity,
|
||||
};
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}, {} as Record<string, any>);
|
||||
|
||||
// Convert the grouped data back to an array
|
||||
const result = Object.values(groupedData);
|
||||
|
||||
// Sort the result array based on the date
|
||||
result?.sort((a, b) => new Date(a?.date) - new Date(b?.date));
|
||||
result?.sort((a, b) => new Date(a?.date).getTime() - new Date(b?.date).getTime());
|
||||
|
||||
// Separate the sorted data back into individual arrays
|
||||
const dates = result?.map(item => item?.date);
|
||||
const notionalAmount = result?.map(item => item?.notionalAmount);
|
||||
const notionalQuantity = result?.map(item => item?.notionalQuantity);
|
||||
const dates = result?.map((item) => item?.date);
|
||||
const notionalAmount = result?.map((item) => item?.notionalAmount);
|
||||
const notionalQuantity = result?.map((item) => item?.notionalQuantity);
|
||||
|
||||
// Compute the average of item?.traded
|
||||
const totalNotionalAmount = notionalAmount?.reduce((acc, item) => acc + item, 0);
|
||||
avgNotionalAmount = totalNotionalAmount / notionalAmount?.length;
|
||||
|
||||
const totalNotionalQuantity = notionalQuantity?.reduce((acc, item) => acc + item, 0);
|
||||
avgNotionalQuantity = totalNotionalQuantity / notionalQuantity?.length;
|
||||
|
||||
|
||||
|
||||
const option = {
|
||||
silent: true,
|
||||
tooltip: {
|
||||
silent: true,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
hideDelay: 100, // Set the delay in milliseconds
|
||||
},
|
||||
animation: false,
|
||||
grid: {
|
||||
hideDelay: 100,
|
||||
},
|
||||
animation: false,
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
bottom: '0%',
|
||||
top: '10%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis:
|
||||
{
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: dates,
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: false, // Disable x-axis grid lines
|
||||
},
|
||||
|
||||
axisLabel: {
|
||||
show: false // Hide y-axis labels
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: false, // Disable x-axis grid lines
|
||||
color: '#fff',
|
||||
},
|
||||
position: 'right',
|
||||
axisLabel: {
|
||||
show: false // Hide y-axis labels
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: 'Notional Amount',
|
||||
type: 'bar',
|
||||
data: notionalAmount,
|
||||
barWidth: '50%',
|
||||
itemStyle: {
|
||||
color: '#8F54F4'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Notional Quantity',
|
||||
type: 'bar',
|
||||
data: notionalQuantity,
|
||||
barWidth: '50%',
|
||||
yAxisIndex: 1,
|
||||
itemStyle: {
|
||||
color: '#FF9E21'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
position: 'right',
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: 'Notional Amount',
|
||||
type: 'scatter',
|
||||
data: dates?.map((date, index) => [date, notionalAmount[index]]),
|
||||
itemStyle: {
|
||||
color: '#8F54F4',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Notional Quantity',
|
||||
type: 'scatter',
|
||||
data: dates?.map((date, index) => [date, notionalQuantity[index]]),
|
||||
yAxisIndex: 1,
|
||||
itemStyle: {
|
||||
color: '#FF9E21',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
return option;
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
async function getSwapData(ticker) {
|
||||
|
||||
async function getSwapData(ticker: string) {
|
||||
const cachedData = getCache(ticker, 'getSwapData');
|
||||
if (cachedData) {
|
||||
rawData = cachedData;
|
||||
} else {
|
||||
try {
|
||||
const postData = {ticker: ticker, path: 'swap-ticker'}
|
||||
const postData = { ticker, path: 'swap-ticker' };
|
||||
const response = await fetch('/api/ticker-data', {
|
||||
method: 'POST',
|
||||
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');
|
||||
rawData = await response.json();
|
||||
@ -199,7 +159,7 @@
|
||||
rawData = [];
|
||||
}
|
||||
}
|
||||
$swapComponent = rawData?.length !== 0;
|
||||
$swapComponent = rawData?.length !== 0; // Correct the use of `$`
|
||||
}
|
||||
|
||||
$: if ($stockTicker && typeof window !== 'undefined') {
|
||||
@ -211,12 +171,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$: charNumber = $screenWidth < 640 ? 20 : 40;
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<svelte:options immutable={true} />
|
||||
|
||||
|
||||
<section class="overflow-hidden text-white h-full pb-8">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user