This commit is contained in:
MuslemRahimi 2025-04-05 21:49:15 +02:00
parent 8693ca0918
commit 66296658a0
28 changed files with 907 additions and 131 deletions

View File

@ -1041,9 +1041,10 @@
<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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -148,14 +148,15 @@
{/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 class="relative">
<label
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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-muted dark:text-gray-400"
></span>
</label>
</div>
</div>
{/if}
{:else}

View File

@ -22,9 +22,11 @@
<div bind:this={el} 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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>
<span
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>
</div>

View File

@ -1573,9 +1573,10 @@ const output = await response.json();
<div class="absolute right-1/2 left-1/2 top-1/2 bottom-1/2">
<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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { abbreviateNumber } from "$lib/utils";
import { setCache, getCache, screenWidth } from "$lib/store";
import { abbreviateNumber, buildOptionSymbol } from "$lib/utils";
import { setCache, getCache } from "$lib/store";
import * as DropdownMenu from "$lib/components/shadcn/dropdown-menu/index.js";
import { Button } from "$lib/components/shadcn/button/index.js";
import Infobox from "$lib/components/Infobox.svelte";
@ -43,25 +43,6 @@
});
};
function buildOptionSymbol(dateExpiration, optionType, strikePrice) {
// Format the expiration date as YYMMDD
const date = new Date(dateExpiration);
const year = date.getFullYear() % 100; // Last two digits of the year
const month = (date.getMonth() + 1).toString().padStart(2, "0"); // Months are 0-indexed
const day = date.getDate().toString().padStart(2, "0");
const expirationStr = `${year}${month}${day}`;
// Convert option type to a single uppercase letter (C for Call, P for Put)
const optionTypeChar = optionType.charAt(0).toUpperCase();
// Format strike price as 8 digits (multiply by 1000 and pad with leading zeros)
const strikePriceScaled = Math.round(strikePrice * 1000);
const strikeStr = strikePriceScaled.toString().padStart(8, "0");
// Combine all components into the final option symbol
return `${ticker}${expirationStr}${optionTypeChar}${strikeStr}`;
}
const currentTime = new Date(
new Date().toLocaleString("en-US", { timeZone: "America/New_York" }),
)?.getTime();
@ -410,6 +391,7 @@
rawDataHistory = [];
optionSymbol = buildOptionSymbol(
ticker,
selectedDate,
selectedOptionType,
selectedStrike,
@ -888,27 +870,32 @@
</table>
</div>
<div class="pb-8 sm:pb-2 rounded-md overflow-hidden">
<div
class="flex flex-row items-center justify-between gap-x-2 ml-auto w-fit mt-2"
>
{#each ["Vol/OI", "IV"] as item}
<label
on:click={() => {
selectGraphType = item;
loadData("default");
}}
class="px-3 py-1.5 {selectGraphType === item
? 'shadow-sm bg-gray-100 dark:bg-white text-black '
: 'shadow-sm text-opacity-[0.6] border border-gray-300 dark:border-gray-600'} transition ease-out duration-100 sm:hover:bg-white sm:hover:text-black rounded-md cursor-pointer"
>
{item}
</label>
{/each}
<div class="mt-5 pb-2 rounded-md overflow-hidden">
<div class="flex flex-row items-center justify-between w-full mt-2">
<h2 class="text-xl sm:text-2xl font-bold text-start">
Contract Chart
</h2>
<div class="w-fit ml-auto">
{#each ["Vol/OI", "IV"] as item, index}
<label
on:click={() => {
selectGraphType = item;
loadData("default");
}}
class="px-3 py-1.5 text-sm {index === 0
? 'mr-2'
: ''} {selectGraphType === item
? 'shadow-sm border border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-white text-black '
: 'shadow-sm text-opacity-[0.6] border border-gray-300 dark:border-gray-600'} transition ease-out duration-100 sm:hover:bg-white sm:hover:text-black rounded-md cursor-pointer"
>
{item}
</label>
{/each}
</div>
</div>
{#if config}
<div>
<div class="grow pt-5">
<div class="grow pt-3">
<div class="relative">
<!-- Apply the blur class to the chart -->
<div
@ -946,6 +933,10 @@
</div>
{#if isLoaded && displayList?.length > 0}
<h2 class="text-xl sm:text-2xl font-bold text-start mt-5">
Contract History
</h2>
<div
class="flex justify-start items-center m-auto overflow-x-auto cursor-normal"
>

View File

@ -1051,9 +1051,10 @@
<div class="m-auto flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-[#272727] rounded-xl 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -1126,9 +1126,10 @@
<div class="m-auto flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-[#272727] rounded-xl 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -269,9 +269,11 @@
<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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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"></span>
<span
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>
</div>

View File

@ -368,10 +368,10 @@
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-default 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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 sm:loading-[1rem] text-gray-400"
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -169,12 +169,14 @@
{: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"></span>
</label>
</div>
<label
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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-muted dark:text-gray-400"
></span>
</label>
</div>
</div>
{/if}
</main>

View File

@ -24,6 +24,26 @@ if (!name) return "";
return wordsToRemove?.reduce((acc, word) => acc.replace(word, "").trim(), name);
}
export function buildOptionSymbol(ticker, dateExpiration, optionType, strikePrice) {
// Format the expiration date as YYMMDD
const date = new Date(dateExpiration);
const year = date.getFullYear() % 100; // Last two digits of the year
const month = (date.getMonth() + 1).toString().padStart(2, "0"); // Months are 0-indexed
const day = date.getDate().toString().padStart(2, "0");
const expirationStr = `${year}${month}${day}`;
// Convert option type to a single uppercase letter (C for Call, P for Put)
const optionTypeChar = optionType.charAt(0).toUpperCase();
// Format strike price as 8 digits (multiply by 1000 and pad with leading zeros)
const strikePriceScaled = Math.round(strikePrice * 1000);
const strikeStr = strikePriceScaled.toString().padStart(8, "0");
// Combine all components into the final option symbol
return `${ticker}${expirationStr}${optionTypeChar}${strikeStr}`;
}
export function convertToSlug(title) {
// Remove punctuation, hyphens, and special characters
const cleanedTitle = title

View File

@ -1309,7 +1309,8 @@
<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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -760,7 +760,7 @@
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"
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -431,9 +431,10 @@
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -771,10 +771,10 @@
>
<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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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"
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -774,7 +774,9 @@
<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>
<span
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>
</div>

View File

@ -1,25 +1,49 @@
export const load = async ({ locals }) => {
const { apiKey, apiURL } = locals;
const { apiKey, apiURL } = locals;
const getData = async () => {
const postData = {
ticker: 'TSLA',
};
// make the POST request to the endpoint
const response = await fetch(apiURL + "/potus-tracker", {
method: "GET",
const response = await fetch(apiURL + "/contract-lookup-summary", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey,
},
body: JSON.stringify(postData),
});
const output = await response.json();
return output;
};
return output;
};
const getStockQuote = async () => {
const postData = { ticker: 'TSLA' };
const response = await fetch(apiURL + "/historical-price", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey,
},
body: JSON.stringify(postData),
});
const output = await response.json();
return output;
};
// Make sure to return a promise
return {
getData: await getData(),
getStockQuote: await getStockQuote(),
};
};

View File

@ -1,19 +1,36 @@
<script lang="ts">
import * as DropdownMenu from "$lib/components/shadcn/dropdown-menu/index.js";
import { Button } from "$lib/components/shadcn/button/index.js";
import SEO from "$lib/components/SEO.svelte";
import { onMount } from "svelte";
import { buildOptionSymbol } from "$lib/utils";
import { setCache, getCache } from "$lib/store";
import { mode } from "mode-watcher";
import highcharts from "$lib/highcharts.ts";
export let data;
let isLoaded = true;
let config = null;
let selectedStrategy = "Long Call";
let selectedOptionType = "Call";
let selectedTicker = "TSLA";
let optionData = data?.getData[selectedOptionType];
let dateList = Object?.keys(optionData);
let selectedDate = Object?.keys(optionData)[0];
let strikeList = optionData[selectedDate] || [];
let selectedStrike = strikeList?.at(0) || [];
let optionSymbol;
let strategies = [
{ name: "Custom Strategy", sentiment: "" },
{ name: "Long Call", sentiment: "Bullish" },
{ name: "Long Put", sentiment: "Bearish" },
{ name: "Short Call", sentiment: "Bearish" },
{ name: "Short Put", sentiment: "Bullish" },
/*
{ name: "Custom Strategy", sentiment: "" },
{ name: "Covered Call", sentiment: "Bullish" },
{ name: "Protective Put", sentiment: "Bullish" },
{ name: "Cash Secured Put", sentiment: "Bullish" },
@ -28,8 +45,28 @@
{ name: "Long Call Butterfly", sentiment: "Neutral" },
{ name: "Long Straddle", sentiment: "Neutral" },
{ name: "Short Straddle", sentiment: "Neutral" },
*/
];
const tradeInfo = {
type: "Long Call",
details: "BUY +1 TSLA Apr 11, 2025 280.0 call @$30.0",
currentPrice: "$239.34",
breakEvenPrice: "$310.00",
costOfTrade: "$3,000.00",
maxProfit: "Unlimited",
maxLoss: "-$3,000.00",
};
const formatDate = (dateString) => {
const date = new Date(dateString);
return date.toLocaleDateString("en-US", {
month: "short",
day: "2-digit",
year: "numeric",
});
};
function plotData() {
const action = "Buy";
const optionType = "Call";
@ -57,7 +94,6 @@
dataPoints.push([s, payoff]);
}
// 2) Create Highcharts configuration
const options = {
credits: {
enabled: false,
@ -79,10 +115,10 @@
tickInterval: 50,
title: {
text: "TSLA Price at Expiration ($)",
style: { color: $mode === "light" ? "black" : "white" },
style: { color: $mode === "light" ? "#545454" : "white" },
},
labels: {
style: { color: $mode === "light" ? "black" : "white" },
style: { color: $mode === "light" ? "#545454" : "white" },
},
plotLines: [
// Strike Price
@ -112,12 +148,12 @@
yAxis: {
title: {
text: "Expected Profit/Loss ($)",
style: { color: $mode === "light" ? "black" : "white" },
style: { color: $mode === "light" ? "#545454" : "white" },
},
gridLineWidth: 1,
gridLineColor: $mode === "light" ? "#e5e7eb" : "#111827",
labels: {
style: { color: $mode === "light" ? "black" : "white" },
style: { color: $mode === "light" ? "#545454" : "white" },
formatter: function () {
return "$" + this.value.toFixed(0);
},
@ -179,6 +215,69 @@
return options;
}
const getContractHistory = async (contractId) => {
let output;
const cachedData = getCache(contractId, "getContractHistory");
if (cachedData) {
output = cachedData;
} else {
const postData = {
ticker: selectedTicker,
contract: contractId,
};
// make the POST request to the endpoint
const response = await fetch("/api/options-contract-history", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(postData),
});
output = await response.json();
setCache(contractId, output, "getContractHistory");
}
return output;
};
async function loadData(state: string) {
isLoaded = false;
optionData = data?.getData[selectedOptionType];
dateList = [...Object?.keys(optionData)];
strikeList = [...optionData[selectedDate]];
if (!strikeList?.includes(selectedStrike)) {
selectedStrike = strikeList?.at(0); // Set to first element if not found
}
optionSymbol = buildOptionSymbol(
selectedTicker,
selectedDate,
selectedOptionType,
selectedStrike,
);
const output = await getContractHistory(optionSymbol);
selectedOptionPrice = output?.history?.at(-1)?.mark;
isLoaded = true;
}
function handleOptionType() {
if (selectedOptionType === "Call") {
selectedOptionType = "Put";
} else {
selectedOptionType = "Call";
}
}
onMount(async () => {
await loadData("default");
});
config = plotData();
</script>
@ -250,67 +349,67 @@
<tr>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Ticker
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Action
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Quantity
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Expiration Date
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Strike
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Type
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Price
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Delta
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
>
Adjustment
</th>
<th
scope="col"
class="px-4 py-3 text-left text-sm font-semibold"
class="px-4 py-1.5 text-left text-sm font-semibold"
></th>
</tr>
</thead>
<!-- Table body -->
<tbody class="bg-white divide-y divide-gray-200 text-sm">
<tbody class="bg-[#F8F9FA] divide-y divide-gray-200 text-sm">
<!-- Example Option Leg Row -->
<tr>
<td class="px-4 py-3 whitespace-nowrap font-bold">
@ -331,24 +430,103 @@
/>
</td>
<td class="px-4 py-3 whitespace-nowrap">
<input
type="date"
class="border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500"
value="2025-05-12"
/>
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button
builders={[builder]}
class="mb-1 border border-gray-300 dark:border-none shadow-sm bg-white dark:bg-[#000] h-[35px] flex flex-row justify-between items-center min-w-[130px] w-[140px] sm:w-auto px-3 rounded-md truncate"
>
<span class="truncate text-sm"
>{formatDate(selectedDate)}</span
>
<svg
class="-mr-1 ml-2 h-5 w-5 inline-block"
viewBox="0 0 20 20"
fill="currentColor"
style="max-width:40px"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content
class="w-auto max-w-60 max-h-[400px] overflow-y-auto scroller relative"
>
<!-- Dropdown items -->
<DropdownMenu.Group class="pb-2"
>{#each dateList as item}
<DropdownMenu.Item
on:click={() => {
selectedDate = item;
loadData("default");
}}
class="sm:hover:bg-gray-200 dark:sm:hover:bg-primary cursor-pointer "
>
{formatDate(item)}
</DropdownMenu.Item>
{/each}</DropdownMenu.Group
>
</DropdownMenu.Content>
</DropdownMenu.Root>
</td>
<td class="px-4 py-3 whitespace-nowrap">
<input
type="number"
step="0.01"
value="280.0"
class="border border-gray-300 rounded px-2 py-1 w-24 focus:outline-none focus:ring-1 focus:ring-blue-500"
/>
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button
builders={[builder]}
class="mb-1 border border-gray-300 dark:border-none shadow-sm bg-white dark:bg-[#000] h-[35px] flex flex-row justify-between items-center min-w-[130px] w-[140px] sm:w-auto px-3 rounded-md truncate"
>
<span class="truncate text-sm"
>{selectedStrike}</span
>
<svg
class="-mr-1 ml-2 h-5 w-5 inline-block"
viewBox="0 0 20 20"
fill="currentColor"
style="max-width:40px"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content
class="w-auto max-w-60 max-h-[400px] overflow-y-auto scroller relative"
>
<!-- Dropdown items -->
<DropdownMenu.Group class="pb-2">
<!-- Added padding to avoid overlapping with Reset button -->
{#each strikeList as item}
<DropdownMenu.Item
on:click={() => {
selectedStrike = item;
loadData("default");
}}
class="sm:hover:bg-gray-200 dark:sm:hover:bg-primary cursor-pointer "
>
{item}
</DropdownMenu.Item>
{/each}
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</td>
<td class="px-4 py-3 whitespace-nowrap">
<label
class="badge px-2 rounded-md bg-blue-100 text-blue-800 font-semibold cursor-pointer"
>Call</label
on:click={handleOptionType}
class="select-none badge px-2 rounded-md bg-blue-100 text-blue-800 font-semibold cursor-pointer"
>{selectedOptionType}</label
>
</td>
<td class="px-4 py-3 whitespace-nowrap">
@ -403,11 +581,550 @@
</tbody>
</table>
</div>
{#if config}
<div
class="shadow-sm mt-5 border border-gray-300 dark:border-gray-800 rounded"
use:highcharts={config}
></div>
{#if isLoaded}
{#if config}
<div
class="shadow-sm mt-5 border border-gray-300 dark:border-gray-800 rounded"
use:highcharts={config}
></div>
{/if}
<div class="mt-5">
<h1 class="text-2xl font-bold text-gray-800 mb-6">
Trade Information
</h1>
<!-- Trade Information Card -->
<div
class="border border-gray-300 dark:border-gray-800 rounded-lg p-4 mb-6 shadow-sm max-w-sm"
>
<div>Long Call</div>
<div class="text-green-800 font-semibold">
BUY +1 TSLA Apr 11, 2025 280.0 call @$30.0
</div>
</div>
<!-- Stock Section -->
<h2 class="text-xl font-bold text-gray-800 mb-4">Stock</h2>
<div class="grid grid-cols-2 sm:grid-cols-4 mb-6">
<div>
<div class="text-gray-600">TSLA Current Price</div>
<div class="flex items-baseline">
<span class="text-lg font-semibold"
>{tradeInfo.currentPrice}</span
>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
TSLA Breakeven Price
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="flex items-baseline">
<span class="text-lg font-semibold"
>{tradeInfo.breakEvenPrice}</span
>
</div>
</div>
</div>
<!-- Trade Details Section -->
<h2 class="text-xl font-bold text-gray-800 mb-4">
Trade Details
</h2>
<div
class="grid grid-cols-2 md:grid-cols-4 gap-y-6 sm:gap-y-0 mb-6"
>
<div>
<div class="flex items-center text-gray-600">
Cost of Trade
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="flex items-baseline">
<span class="text-lg font-semibold"
>{tradeInfo.costOfTrade}</span
>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Maximum Profit
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-lg font-semibold text-green-800">
{tradeInfo.maxProfit}
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Maximum Loss
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-lg font-semibold text-red-600">
{tradeInfo.maxLoss}
</div>
</div>
</div>
<!--
<h2 class="text-xl font-bold text-gray-800 mb-4">
Probability Analysis
</h2>
<div class="grid grid-cols-2 md:grid-cols-4 mb-6">
<div>
<div class="flex items-center text-gray-600">
Probability of Profit (PoP)
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-start">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Probability of Max Profit
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Probability of Max Loss
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
</div>
<h2 class="text-xl font-bold text-gray-800 mb-4">
Risk Reward Analysis
</h2>
<div class="grid grid-cols-2 md:grid-cols-3 gap-6 mb-6">
<div>
<div class="flex items-center text-gray-600">
Expected Value (EV)
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Expected Return (EV/risk)
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Reward/Risk
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
</div>
<h2
class="text-xl font-bold text-gray-800 mb-4 flex items-center"
>
Position Greeks
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-6 mb-6">
<div>
<div class="flex items-center text-gray-600">
Delta (Δ)
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Gamma (Γ)
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Theta (Θ)
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
<div>
<div class="flex items-center text-gray-600">
Vega (v)
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 ml-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="text-xl text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 mx-auto"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
</div>
</div>
</div>
-->
</div>
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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-muted dark:text-gray-400"
></span>
</label>
</div>
</div>
{/if}
</div>
</div>

View File

@ -356,9 +356,10 @@
<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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -797,7 +797,9 @@
<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>
<span
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>
</div>

View File

@ -3529,9 +3529,11 @@ const handleKeyDown = (event) => {
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-primary rounded-xl 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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>
<span
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>
</div>

View File

@ -766,7 +766,7 @@
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"
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -250,9 +250,10 @@
<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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -279,9 +279,10 @@
<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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -162,7 +162,7 @@
</h2>
<div
class="no-scrollbar flex justify-start items-center w-screen sm:w-full mt-6 m-auto overflow-x-auto pr-5 sm:pr-0"
class="no-scrollbar flex justify-start items-center w-screen sm:w-full mt-6 m-auto overflow-x-auto ovef pr-5 sm:pr-0"
>
<table
class="table table-sm table-compact no-scrollbar rounded-none sm:rounded-md w-full border border-gray-300 dark:border-gray-800 m-auto"
@ -175,7 +175,7 @@
>
{#each geographicXData as item}
<th
class="z-20 bg-default border-b border-gray-800 text-white font-semibold text-sm text-center bg-default"
class="z-20 border-b border-gray-300 dark:border-gray-800 font-semibold text-sm text-center"
>{new Date(item ?? null)?.toLocaleString("en-US", {
month: "short",
day: "numeric",

View File

@ -1108,9 +1108,10 @@
<div class="m-auto flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-[#272727] rounded-xl 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>

View File

@ -1995,9 +1995,10 @@
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded 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"
class="shadow-sm bg-gray-300 dark:bg-secondary rounded 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
class="loading loading-spinner loading-md text-muted dark:text-gray-400"
></span>
</label>
</div>