update dark pool page

This commit is contained in:
MuslemRahimi 2024-12-29 16:00:12 +01:00
parent 76af2185b4
commit 797be0b88b
6 changed files with 526 additions and 514 deletions

View File

@ -154,15 +154,15 @@
<main class="overflow-hidden">
<div class="flex flex-row items-center">
<label
for="darkPoolInfo"
for="historicalDataInfo"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
>
Historical Activity
</label>
<InfoModal
title={"Dark Pool Data"}
content={"Dark pool data refers to information on trading activities that occur in private, non-public financial exchanges known as dark pools. These venues are used by hedge funds and major institutional traders to buy and sell large blocks of securities without exposing their orders to the public, minimizing market impact and price fluctuations. Currently, nearly 50% of all trades are executed in these dark pools, highlighting their significant role in the trading landscape."}
id={"darkPoolInfo"}
title={"Historical Data"}
content={"By analyzing historical dark pool activity, retail investors can gauge market sentiment through total and short volumes. High short volume may indicate bearish sentiment."}
id={"historicalDataInfo"}
/>
</div>

View File

@ -0,0 +1,282 @@
<script lang="ts">
import { stockTicker, etfTicker } from "$lib/store";
import InfoModal from "$lib/components/InfoModal.svelte";
import TableHeader from "$lib/components/Table/TableHeader.svelte";
import { abbreviateNumberWithColor } from "$lib/utils";
export let rawData = [
{
date: "2024-12-27T17:52:33Z",
price: 31.89,
size: 14526,
volume: 6937280.0,
premium: "463232.6874",
sizeVolRatio: 0.21,
sizeAvgVolRatio: 0.14,
trackingID: 46353769264496,
rank: 1,
},
{
date: "2024-12-27T17:52:33Z",
price: 31.89,
size: 14526,
volume: 6937280.0,
premium: "463232.6874",
sizeVolRatio: 0.21,
sizeAvgVolRatio: 0.14,
trackingID: 46353769264496,
rank: 2,
},
{
date: "2024-12-27T18:03:31Z",
price: 32.0,
size: 12198,
volume: 7146904.0,
premium: "390336",
sizeVolRatio: 0.17,
sizeAvgVolRatio: 0.12,
trackingID: 47011633532241,
rank: 3,
},
{
date: "2024-12-27T18:03:31Z",
price: 32.0,
size: 12198,
volume: 7146904.0,
premium: "390336",
sizeVolRatio: 0.17,
sizeAvgVolRatio: 0.12,
trackingID: 47011633532241,
rank: 4,
},
{
date: "2024-12-27T20:00:53Z",
price: 31.78,
size: 7345,
volume: 8220987.0,
premium: "233424.10",
sizeVolRatio: 0.09,
sizeAvgVolRatio: 0.07,
trackingID: 54053503366366,
rank: 5,
},
];
let stockList = [];
let isLoaded = false;
function formatToNewYorkTime(isoString) {
const date = new Date(isoString);
// Get the date components in New York time zone
const options = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZone: "America/New_York",
hour12: true, // Enable AM/PM format
};
// Format date for New York timezone
const formatter = new Intl.DateTimeFormat("en-US", options);
const parts = formatter.formatToParts(date);
const year = parts.find((p) => p.type === "year").value;
const day = parts.find((p) => p.type === "day").value;
const hour = parts.find((p) => p.type === "hour").value.padStart(2, "0");
const minute = parts
.find((p) => p.type === "minute")
.value.padStart(2, "0");
const ampm = parts.find((p) => p.type === "dayPeriod").value; // AM/PM
return `${day}/${year} ${hour}:${minute} ${ampm}`;
}
$: columns = [
{ key: "rank", label: "Rank", align: "left" },
{ key: "date", label: "Time", align: "left" },
{ key: "price", label: "Price", align: "right" },
{ key: "size", label: "Size", align: "right" },
{ key: "volume", label: "Volume", align: "right" },
{ key: "sizeVolRatio", label: "Size / Vol", align: "right" },
{ key: "sizeAvgVolRatio", label: "Size / Avg Vol", align: "right" },
{ key: "premium", label: "Premium", align: "right" },
];
$: sortOrders = {
rank: { order: "none", type: "number" },
date: { order: "none", type: "date" },
price: { order: "none", type: "number" },
size: { order: "none", type: "number" },
volume: { order: "none", type: "number" },
sizeVolRatio: { order: "none", type: "number" },
sizeAvgVolRatio: { order: "none", type: "number" },
premium: { order: "none", type: "number" },
};
const sortData = (key) => {
// Reset all other keys to 'none' except the current key
for (const k in sortOrders) {
if (k !== key) {
sortOrders[k].order = "none";
}
}
// Cycle through 'none', 'asc', 'desc' for the clicked key
const orderCycle = ["none", "asc", "desc"];
let originalData = rawData;
const currentOrderIndex = orderCycle.indexOf(sortOrders[key].order);
sortOrders[key].order =
orderCycle[(currentOrderIndex + 1) % orderCycle.length];
const sortOrder = sortOrders[key].order;
// Reset to original data when 'none' and stop further sorting
if (sortOrder === "none") {
stockList = originalData?.slice(0, 50); // Reset displayed data
return;
}
// Define a generic comparison function
const compareValues = (a, b) => {
const { type } = sortOrders[key];
let valueA, valueB;
switch (type) {
case "date":
valueA = new Date(a[key]);
valueB = new Date(b[key]);
break;
case "string":
valueA = a[key].toUpperCase();
valueB = b[key].toUpperCase();
return sortOrder === "asc"
? valueA.localeCompare(valueB)
: valueB.localeCompare(valueA);
case "number":
default:
valueA = parseFloat(a[key]);
valueB = parseFloat(b[key]);
break;
}
if (sortOrder === "asc") {
return valueA < valueB ? -1 : valueA > valueB ? 1 : 0;
} else {
return valueA > valueB ? -1 : valueA < valueB ? 1 : 0;
}
};
// Sort using the generic comparison function
stockList = [...originalData].sort(compareValues)?.slice(0, 50);
};
$: if (typeof window !== "undefined" && ($stockTicker || $etfTicker)) {
isLoaded = false;
stockList = rawData;
isLoaded = true;
}
</script>
<section class="overflow-hidden text-white h-full pb-8">
<main class="overflow-hidden">
<div class="flex flex-row items-center">
<label
for="hottestDPTrade"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
>
Hottest Trades
</label>
<InfoModal
title={"Hottest DP Trades"}
content={"Real-time hottest trades highlight significant premium flows, revealing where big players are active and hinting at market trends or sentiment."}
id={"hottestDPTrade"}
/>
</div>
{#if isLoaded}
{#if rawData?.length !== 0}
<div class="w-full flex flex-col items-start">
<div class="text-white text-[1rem] mt-2 mb-2 w-full">
Get in realtime the latest hottest trades based on premium.
</div>
</div>
<div
class="w-full m-auto rounded-none sm:rounded-md mb-4 overflow-x-scroll"
>
<table
class="table table-sm table-compact no-scrollbar rounded-none sm:rounded-md text-white w-full bg-table border border-gray-800 m-auto"
>
<thead>
<TableHeader {columns} {sortOrders} {sortData} />
</thead>
<tbody>
{#each stockList as item, index}
<tr
class="sm:hover:bg-[#245073] border-b border-gray-800 sm:hover:bg-opacity-[0.2] odd:bg-odd"
>
<td
class="text-start text-sm sm:text-[1rem] whitespace-nowrap text-white"
>
{item?.rank}
</td>
<td
class="text-start text-sm sm:text-[1rem] whitespace-nowrap text-white"
>
{formatToNewYorkTime(item?.date)}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap text-white"
>
{item?.price}
</td>
<td class="text-sm sm:text-[1rem] text-end">
{@html abbreviateNumberWithColor(item?.size, false, true)}
</td>
<td class="text-sm sm:text-[1rem] text-end">
{@html abbreviateNumberWithColor(item?.volume, false, true)}
</td>
<td class="text-sm sm:text-[1rem] text-end">
{item?.sizeVolRatio?.toFixed(2)}%
</td>
<td class="text-sm sm:text-[1rem] text-end">
{item?.sizeAvgVolRatio?.toFixed(2)}%
</td>
<td class="text-sm sm:text-[1rem] text-end">
{@html abbreviateNumberWithColor(
item?.premium,
false,
true,
)}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span class="loading loading-spinner loading-md text-gray-400"
></span>
</label>
</div>
</div>
{/if}
</main>
</section>

View File

@ -0,0 +1,211 @@
<script lang="ts">
import { displayCompanyName, stockTicker, etfTicker } from "$lib/store";
import InfoModal from "$lib/components/InfoModal.svelte";
import { Chart } from "svelte-echarts";
import { abbreviateNumber, abbreviateNumberWithColor } from "$lib/utils";
import { init, use } from "echarts/core";
import { BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
let category = "Size";
use([BarChart, GridComponent, TooltipComponent, CanvasRenderer]);
export let rawData = [];
export let metrics = {};
let isLoaded = false;
let optionsData;
function getPlotOptions(category) {
const xAxis = rawData.map((item) => item[category?.toLowerCase()]); // Convert volume to millions for clarity
const yAxis = rawData.map((item) => item?.price_level || 0);
const options = {
silent: true,
tooltip: {
trigger: "axis",
hideDelay: 100,
borderColor: "#969696",
borderWidth: 1,
backgroundColor: "#313131",
textStyle: {
color: "#fff",
},
formatter: function (params) {
const priceLevel = params[0].axisValue;
let result = `Price Level: ${priceLevel}<br/>`;
params?.forEach((param) => {
const marker =
'<span style="display:inline-block;margin-right:4px;' +
"border-radius:10px;width:10px;height:10px;background-color:" +
param.color +
'"></span>';
result += `${param.seriesName}: ${abbreviateNumber(param.value)}<br/>`;
});
return result;
},
axisPointer: {
lineStyle: {
color: "#fff",
},
},
},
animation: false,
grid: {
left: "0%", // Adjust to create space for y-axis labels
right: "10%",
bottom: "5%",
top: "5%",
containLabel: true,
},
xAxis: {
type: "value",
name: "",
splitLine: { show: false },
axisLabel: {
color: "#fff",
interval: 0, // Show all labels
rotate: 45, // Rotate labels for better readability
fontSize: 12, // Adjust font size if needed
margin: 10,
formatter: function (value) {
return abbreviateNumber(value); // Call your abbreviateNumber function
},
},
},
yAxis: {
type: "category",
name: "",
data: yAxis,
axisLabel: { color: "#fff" },
},
series: [
{
name: `Total ${category}`,
data: xAxis,
type: "bar",
itemStyle: {
color: (params) => {
// Highlight a specific bar (e.g., the maximum volume)
const maxVolumeIndex = xAxis.indexOf(Math.max(...xAxis));
return params.dataIndex === maxVolumeIndex
? "#3BA272"
: "#e2e8f0"; // Green for highlight, blue for others
},
},
showSymbol: false,
},
],
};
return options;
}
$: if (
typeof window !== "undefined" &&
($stockTicker || $etfTicker) &&
category
) {
isLoaded = false;
optionsData = getPlotOptions(category);
isLoaded = true;
}
</script>
<section class="overflow-hidden text-white h-full pb-8 pt-6">
<main class="overflow-hidden">
<div class="flex flex-row items-center">
<label
for="priceLevelInfo"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
>
Price Level
</label>
<InfoModal
title={"Price Level"}
content={"Price levels reveal where significant trading activity occurs, aiding investors in identifying key support and resistance zones."}
id={"priceLevelInfo"}
/>
</div>
{#if isLoaded}
{#if rawData?.length !== 0}
<div class="w-full flex flex-col items-start">
<div class="text-white text-[1rem] mt-2 mb-2 w-full">
Over the past week, GameStop Corp. has seen an average dark pool
trade size of {@html abbreviateNumberWithColor(
metrics?.avgTradeSize,
false,
true,
)}, a total volume of {@html abbreviateNumberWithColor(
metrics?.totalVolume,
false,
true,
)} and an average premium per trade of {@html abbreviateNumberWithColor(
metrics?.avgPremTrade,
false,
true,
)}, with a total premium of {@html abbreviateNumberWithColor(
metrics?.totalPrem,
false,
true,
)}
</div>
</div>
<div class="pb-2 rounded-md bg-default">
<div class="app w-full h-[300px] mt-5 relative">
<div
class="flex justify-start space-x-2 absolute right-0 -top-8 z-10 text-sm"
>
{#each ["Size", "Premium"] as item}
<label
on:click={() => (category = item)}
class="px-4 py-2 {category === item
? 'bg-white text-black shadow-xl'
: 'text-white bg-table text-opacity-[0.6]'} transition ease-out duration-100 sm:hover:bg-white sm:hover:text-black rounded-md cursor-pointer"
>
{item}
</label>
{/each}
</div>
<Chart {init} options={optionsData} class="chart " />
</div>
</div>
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span class="loading loading-spinner loading-md text-gray-400"
></span>
</label>
</div>
</div>
{/if}
</main>
</section>
<style>
.app {
height: 300px;
max-width: 100%; /* Ensure chart width doesn't exceed the container */
}
@media (max-width: 640px) {
.app {
height: 210px;
}
}
.chart {
width: 100%;
}
</style>

View File

@ -1,270 +0,0 @@
<script lang="ts">
import { stockTicker, etfTicker } from "$lib/store";
import InfoModal from "$lib/components/InfoModal.svelte";
import { Chart } from "svelte-echarts";
import { abbreviateNumber } from "$lib/utils";
import { init, use } from "echarts/core";
import { BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
let category = "Volume";
use([BarChart, GridComponent, TooltipComponent, CanvasRenderer]);
export let rawData = [
{ price_level: 31.78, volume: 48562602.0, size: 31490, premium: 1000746.8 },
{
price_level: 31.67,
volume: 46661214.0,
size: 28400,
premium: 899429.8400000001,
},
{
price_level: 31.7,
volume: 29795872.0,
size: 22798,
premium: 722699.5586,
},
{ price_level: 31.65, volume: 28530280.0, size: 22000, premium: 696289.0 },
{ price_level: 31.2, volume: 26279878.0, size: 30516, premium: 952028.3 },
{ price_level: 31.24, volume: 19203098.0, size: 27600, premium: 862246.1 },
];
let isLoaded = false;
let optionsData;
function getPlotOptions() {
const xAxis = rawData.map((item) => item?.volume); // Convert volume to millions for clarity
const yAxis = rawData.map((item) => item?.price_level || 0);
const options = {
silent: true,
tooltip: {
trigger: "axis",
hideDelay: 100,
borderColor: "#969696",
borderWidth: 1,
backgroundColor: "#313131",
textStyle: {
color: "#fff",
},
formatter: function (params) {
const priceLevel = params[0].axisValue;
let result = `Price Level: ${priceLevel}<br/>`;
params?.forEach((param) => {
const marker =
'<span style="display:inline-block;margin-right:4px;' +
"border-radius:10px;width:10px;height:10px;background-color:" +
param.color +
'"></span>';
result += `${marker}${param.seriesName}: ${param.value} M<br/>`;
});
return result;
},
axisPointer: {
lineStyle: {
color: "#fff",
},
},
},
animation: false,
grid: {
left: "0%", // Adjust to create space for y-axis labels
right: "10%",
bottom: "5%",
top: "5%",
containLabel: true,
},
xAxis: {
type: "value",
name: "",
nameTextStyle: { color: "#fff" },
splitLine: { show: false },
axisLabel: {
color: "#fff",
interval: 0, // Show all labels
rotate: 45, // Rotate labels for better readability
fontSize: 12, // Adjust font size if needed
margin: 10,
formatter: function (value) {
return abbreviateNumber(value); // Call your abbreviateNumber function
},
},
},
yAxis: {
type: "category",
name: "Price Level",
nameTextStyle: { color: "#fff" },
data: yAxis,
axisLabel: { color: "#fff" },
},
series: [
{
name: "Total Volume",
data: xAxis,
type: "bar",
itemStyle: {
color: (params) => {
// Highlight a specific bar (e.g., the maximum volume)
const maxVolumeIndex = xAxis.indexOf(Math.max(...xAxis));
return params.dataIndex === maxVolumeIndex
? "#3BA272"
: "#e2e8f0"; // Green for highlight, blue for others
},
},
showSymbol: false,
},
],
};
return options;
}
$: if (typeof window !== "undefined" && ($stockTicker || $etfTicker)) {
isLoaded = false;
optionsData = getPlotOptions();
isLoaded = true;
}
</script>
<section class="overflow-hidden text-white h-full pb-8">
<main class="overflow-hidden">
<div class="flex flex-row items-center">
<label
for="darkPoolLevel"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
>
Price Level
</label>
<InfoModal
title={"Dark Pool Price Level"}
content={"Dark pool data refers to information on trading activities that occur in private, non-public financial exchanges known as dark pools. These venues are used by hedge funds and major institutional traders to buy and sell large blocks of securities without exposing their orders to the public, minimizing market impact and price fluctuations. Currently, nearly 50% of all trades are executed in these dark pools, highlighting their significant role in the trading landscape."}
id={"darkPoolLevel"}
/>
</div>
{#if isLoaded}
{#if rawData?.length !== 0}
<!--
<div class="w-full flex flex-col items-start">
<div class="text-white text-[1rem] mt-2 mb-2 w-full">
Over the past 12 months, {$displayCompanyName} has experienced an average
dark pool trading volume of
<span class="font-semibold">{abbreviateNumber(avgVolume)}</span>
shares. Out of this total, an average of
<span class="font-semibold">{abbreviateNumber(avgShortVolume)}</span
>
shares, constituting approximately
<span class="font-semibold"
>{((avgShortVolume / avgVolume) * 100)?.toFixed(2)}%</span
>, were short volume.
</div>
</div>
-->
<div class="w-full flex flex-col items-start">
Over the past 12 months, GameStop Corp. has experienced an average
dark pool trading volume of 8.55M shares. Out of this total, an
average of 3.81M shares, constituting approximately 44.52%, were short
volume.
</div>
<div class="pb-2 rounded-md bg-default">
<div class="app w-full h-[300px] mt-5 relative">
<div
class="flex justify-start space-x-2 absolute right-0 top-0 z-10 text-sm"
>
{#each ["Volume", "Size", "Premium"] as item}
<label
on:click={() => (category = item)}
class="px-4 py-2 {category === item
? 'bg-white text-black shadow-xl'
: 'text-white bg-table text-opacity-[0.6]'} transition ease-out duration-100 sm:hover:bg-white sm:hover:text-black rounded-md cursor-pointer"
>
{item}
</label>
{/each}
</div>
<Chart {init} options={optionsData} class="chart" />
</div>
</div>
<!--
<h2
class="mt-10 mr-1 flex flex-row items-center text-white text-xl sm:text-2xl font-bold mb-3"
>
Latest Information
</h2>
<div class="flex justify-start items-center w-full m-auto">
<table class="w-full bg-table border border-gray-800">
<tbody>
<tr class="border-y border-gray-800 odd:bg-odd">
<td class="px-[5px] py-1.5 xs:px-2.5 xs:py-2">
<span>Date</span>
</td>
<td
class="text-sm sm:text-[1rem] px-[5px] py-1.5 whitespace-nowrap text-right font-medium xs:px-2.5 xs:py-2"
>
{formatDateRange(rawData?.slice(-1)?.at(0)?.date)}
</td>
</tr>
<tr class="border-y border-gray-800 whitespace-nowrap odd:bg-odd">
<td class="px-[5px] py-1.5 xs:px-2.5 xs:py-2">
<span>Total Volume</span>
</td>
<td
class="px-[5px] py-1.5 text-right font-medium xs:px-2.5 xs:py-2"
>
{monthlyVolume}
</td>
</tr>
<tr class="border-y border-gray-800 whitespace-nowrap odd:bg-odd">
<td class="px-[5px] py-1.5 xs:px-2.5 xs:py-2">
<span>Avg. Short % of Volume</span>
</td>
<td
class="px-[5px] py-1.5 text-right font-medium xs:px-2.5 xs:py-2"
>
{avgMonthlyShort}%
</td>
</tr>
</tbody>
</table>
</div>
-->
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span class="loading loading-spinner loading-md text-gray-400"
></span>
</label>
</div>
</div>
{/if}
</main>
</section>
<style>
.app {
height: 300px;
max-width: 100%; /* Ensure chart width doesn't exceed the container */
}
@media (max-width: 640px) {
.app {
height: 210px;
}
}
.chart {
width: 100%;
}
</style>

View File

@ -10,10 +10,10 @@ export const load = async ({ params, locals }) => {
ticker: params.tickerID,
};
const getStockDividend = async () => {
const getPriceLevel = async () => {
const response = await fetch(apiURL + "/stock-dividend", {
const response = await fetch(apiURL + "/dark-pool-level", {
method: "POST",
headers: {
"Content-Type": "application/json",
@ -47,7 +47,7 @@ export const load = async ({ params, locals }) => {
// Make sure to return a promise
return {
getStockDividend: await getStockDividend(),
getPriceLevel: await getPriceLevel(),
getHistoricalDarkPool: await getHistoricalDarkPool(),
};

View File

@ -4,120 +4,14 @@
displayCompanyName,
stockTicker,
} from "$lib/store";
import { onMount } from "svelte";
import { monthNames } from "$lib/utils";
import DarkPool from "$lib/components/DarkPool.svelte";
import DarkPoolLevel from "$lib/components/DarkPoolLevel.svelte";
import HistoricalVolume from "$lib/components/DarkPool/HistoricalVolume.svelte";
import PriceLevel from "$lib/components/DarkPool/PriceLevel.svelte";
import InfoModal from "$lib/components/InfoModal.svelte";
import { Chart } from "svelte-echarts";
import { init, use } from "echarts/core";
import { LineChart, BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
import Infobox from "$lib/components/Infobox.svelte";
use([LineChart, BarChart, TooltipComponent, GridComponent, CanvasRenderer]);
import HottestTrades from "$lib/components/DarkPool/HottestTrades.svelte";
export let data;
let isLoaded = false;
let dateDistance;
let rawData = data?.getStockDividend;
let historicalDarkPool = data?.getHistoricalDarkPool || [];
let optionsDividend;
async function plotDividend() {
// Combine the data into an array of objects to keep them linked
const combinedData = rawData?.history?.map((item) => ({
date: item?.paymentDate,
dividend: item?.adjDividend?.toFixed(3),
}));
// Sort the combined data array based on the date
combinedData.sort((a, b) => new Date(a?.date) - new Date(b?.date));
// Separate the sorted data back into individual arrays
const dates = combinedData.map((item) => item.date);
const dividendList = combinedData?.map((item) => item.dividend);
const options = {
animation: false,
grid: {
left: "3%",
right: "3%",
bottom: "10%",
top: "10%",
containLabel: true,
},
xAxis: {
type: "category",
boundaryGap: false,
data: dates,
axisLabel: {
color: "#fff",
formatter: function (value) {
// Assuming dates are in the format 'yyyy-mm-dd'
// Extract the month and day from the date string and convert the month to its abbreviated name
const dateParts = value.split("-");
const year = dateParts[0].substring(2); // Extracting the last two digits of the year
const monthIndex = parseInt(dateParts[1]) - 1; // Months are zero-indexed in JavaScript Date objects
return `${monthNames[monthIndex]} '${year} `;
},
},
},
yAxis: [
{
type: "value",
splitLine: {
show: false, // Disable x-axis grid lines
},
axisLabel: {
show: false, // Hide y-axis labels
},
},
],
series: [
{
name: "Dividend per Share",
data: dividendList,
type: "bar",
smooth: true,
itemStyle: {
color: "#fff",
},
},
],
tooltip: {
trigger: "axis",
hideDelay: 100,
borderColor: "#969696", // Black border color
borderWidth: 1, // Border width of 1px
backgroundColor: "#313131", // Optional: Set background color for contrast
textStyle: {
color: "#fff", // Optional: Text color for better visibility
},
formatter: function (params) {
const date = params[0].name; // Get the date from the x-axis value
const dateParts = date.split("-");
const year = dateParts[0];
const monthIndex = parseInt(dateParts[1]) - 1;
const day = dateParts[2];
const formattedDate = `${monthNames[monthIndex]} ${day}, ${year}`;
// Return the tooltip content
return `${formattedDate}<br/> Dividend Per Share: ${params[0].value}`;
},
},
};
return options;
}
onMount(async () => {
optionsDividend = await plotDividend();
isLoaded = true;
});
</script>
<svelte:head>
@ -164,136 +58,31 @@
class="w-full relative flex justify-center items-center overflow-hidden"
>
<div class="sm:p-7 w-full m-auto mt-2 sm:mt-0">
<div class="w-full mb-6">
<h1 class="text-xl sm:text-2xl text-white font-bold mb-4 w-full">
Dark Pool
</h1>
<div class="w-full mb-2">
<div class="flex flex-row items-center">
<label
for="darkPoolInfo"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
>
Dark Pool Data
</label>
<InfoModal
title={"Dark Pool Data"}
content={"Dark pool data refers to information on trading activities that occur in private, non-public financial exchanges known as dark pools. These venues are used by hedge funds and major institutional traders to buy and sell large blocks of securities without exposing their orders to the public, minimizing market impact and price fluctuations. Currently, nearly 50% of all trades are executed in these dark pools, highlighting their significant role in the trading landscape."}
id={"darkPoolInfo"}
/>
</div>
<Infobox
text="Track the Dark Pool Trades of major whales to monitor hidden trading activity and trends."
/>
</div>
<DarkPoolLevel />
<DarkPool rawData={historicalDarkPool} />
{#if rawData?.history?.length !== 0}
<div
class="flex flex-col sm:flex-row items-start sm:items-center w-full mt-14 mb-8"
>
<h3 class="text-xl text-white font-semibold">Dividends History</h3>
</div>
{#if isLoaded}
{#if rawData?.history?.length !== 0 && optionsDividend}
<div class="app w-full">
<Chart {init} options={optionsDividend} class="chart" />
</div>
<div
class="overflow-x-scroll no-scrollbar flex justify-start items-center w-full m-auto rounded-none sm:rounded-md mb-4"
>
<table
class="table table-sm table-compact flex justify-start items-center w-full m-auto"
>
<thead>
<tr class="bg-default border-b border-gray-800">
<th
class="text-start bg-default text-white text-sm font-semibold"
>
Ex-Divid. Date
</th>
<th
class="text-end bg-default text-white text-sm font-semibold"
>
Cash Amount
</th>
<th
class="text-end bg-default text-white text-sm font-semibold"
>
Record Date
</th>
<th
class="text-end bg-default text-white text-sm font-semibold"
>
Pay Date
</th>
</tr>
</thead>
<tbody class="">
{#each rawData?.history as item}
<tr
class="text-white odd:bg-odd border-b border-gray-800"
>
<td
class="text-start text-sm sm:text-[1rem] whitespace-nowrap text-white font-medium"
>
{new Date(item?.date)?.toLocaleString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
daySuffix: "2-digit",
})}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap text-white"
>
{item?.adjDividend?.toFixed(3)}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap text-white"
>
{item?.recordDate?.length !== 0
? new Date(item?.recordDate)?.toLocaleString(
"en-US",
{
month: "short",
day: "numeric",
year: "numeric",
daySuffix: "2-digit",
},
)
: "n/a"}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap text-white"
>
{item?.paymentDate?.length !== 0
? new Date(item?.paymentDate)?.toLocaleString(
"en-US",
{
month: "short",
day: "numeric",
year: "numeric",
daySuffix: "2-digit",
},
)
: "n/a"}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<span class="text-white text-sm italic">
* Dividend amounts are adjusted for stock splits when
applicable.
</span>
{:else}
<h1
class="text-xl m-auto flex justify-center text-white mb-4 mt-10"
>
No history found
</h1>
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span class="loading loading-spinner loading-md text-gray-400"
></span>
</label>
</div>
</div>
{/if}
{/if}
<PriceLevel
rawData={data?.getPriceLevel?.priceLevel}
metrics={data?.getPriceLevel?.metrics}
/>
<HottestTrades rawData={data?.getPriceLevel?.hottestTrades} />
<HistoricalVolume rawData={historicalDarkPool} />
</div>
</div>
</div>