update calculator
This commit is contained in:
parent
c7cb9d9440
commit
07638762d3
@ -37,14 +37,14 @@
|
|||||||
|
|
||||||
let optionSymbol;
|
let optionSymbol;
|
||||||
let breakEvenPrice;
|
let breakEvenPrice;
|
||||||
let premium;
|
let totalPremium;
|
||||||
let limits = {};
|
let limits = {};
|
||||||
let rawData = {};
|
let rawData = {};
|
||||||
|
|
||||||
let searchBarData = [];
|
let searchBarData = [];
|
||||||
let timeoutId;
|
let timeoutId;
|
||||||
|
|
||||||
let inputValue = selectedTicker;
|
let inputValue = "";
|
||||||
let touchedInput = false;
|
let touchedInput = false;
|
||||||
let prebuiltStrategy = [
|
let prebuiltStrategy = [
|
||||||
{
|
{
|
||||||
@ -160,37 +160,71 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
function plotData() {
|
function plotData() {
|
||||||
// total premium paid for 1 contract (premium is calculated per share times 100 shares)
|
userStrategy = [
|
||||||
premium = selectedOptionPrice * 100 * selectedQuantity;
|
{
|
||||||
|
action: selectedAction,
|
||||||
|
quantity: selectedQuantity,
|
||||||
|
date: selectedDate,
|
||||||
|
strike: selectedStrike,
|
||||||
|
optionType: selectedOptionType,
|
||||||
|
optionPrice: selectedOptionPrice,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// Create a key from the selected action and option type
|
// Determine x-axis range based on current stock price and max leg strike
|
||||||
const scenarioKey = `${selectedAction} ${selectedOptionType}`;
|
const maxLegStrike = Math.max(...userStrategy?.map((leg) => leg.strike));
|
||||||
|
const xMin = 0;
|
||||||
|
const xMax = Math.floor(Math.max(currentStockPrice, maxLegStrike) * 3);
|
||||||
|
const step = 10;
|
||||||
|
|
||||||
// Calculate break-even price per share using the mapping above.
|
// Calculate the total premium across all legs
|
||||||
// Note: For display, we assume optionPrice is per share.
|
totalPremium = userStrategy?.reduce((sum, leg) => {
|
||||||
breakEvenPrice;
|
return sum + leg.optionPrice * 100 * leg.quantity;
|
||||||
if (breakEvenCalculators[scenarioKey]) {
|
}, 0);
|
||||||
breakEvenPrice = breakEvenCalculators[scenarioKey](
|
|
||||||
selectedStrike,
|
// Compute the aggregated payoff at each underlying price
|
||||||
selectedOptionPrice,
|
const dataPoints = [];
|
||||||
|
for (let s = xMin; s <= xMax; s += step) {
|
||||||
|
let aggregatedPayoff = 0;
|
||||||
|
userStrategy.forEach((leg) => {
|
||||||
|
const legPremium = leg.optionPrice * 100 * leg.quantity;
|
||||||
|
const scenarioKey = `${leg.action} ${leg.optionType}`;
|
||||||
|
if (payoffFunctions[scenarioKey]) {
|
||||||
|
aggregatedPayoff += payoffFunctions[scenarioKey](
|
||||||
|
s,
|
||||||
|
leg.strike,
|
||||||
|
legPremium,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.error("Break-even scenario not implemented:", scenarioKey);
|
console.error(
|
||||||
breakEvenPrice = selectedStrike; // default fallback
|
"Payoff function not implemented for scenario:",
|
||||||
|
scenarioKey,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dataPoints.push([s, aggregatedPayoff]);
|
||||||
}
|
}
|
||||||
|
|
||||||
limits = {};
|
if (userStrategy.length === 1) {
|
||||||
|
const leg = userStrategy[0];
|
||||||
|
const scenarioKey = `${leg?.action} ${leg?.optionType}`;
|
||||||
|
if (breakEvenCalculators[scenarioKey]) {
|
||||||
|
breakEvenPrice = breakEvenCalculators[scenarioKey](
|
||||||
|
leg.strike,
|
||||||
|
leg.optionPrice,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (scenarioKey === "Buy Call") {
|
if (scenarioKey === "Buy Call") {
|
||||||
limits = {
|
limits = {
|
||||||
maxProfit: "Unlimited",
|
maxProfit: "Unlimited",
|
||||||
maxLoss: `-$${premium?.toLocaleString("en-US", {
|
maxLoss: `-$${totalPremium.toLocaleString("en-US", {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2,
|
maximumFractionDigits: 2,
|
||||||
})}`,
|
})}`,
|
||||||
};
|
};
|
||||||
} else if (scenarioKey === "Sell Call") {
|
} else if (scenarioKey === "Sell Call") {
|
||||||
limits = {
|
limits = {
|
||||||
maxProfit: `$${premium?.toLocaleString("en-US", {
|
maxProfit: `$${totalPremium.toLocaleString("en-US", {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2,
|
maximumFractionDigits: 2,
|
||||||
})}`,
|
})}`,
|
||||||
@ -198,27 +232,25 @@
|
|||||||
};
|
};
|
||||||
} else if (scenarioKey === "Buy Put") {
|
} else if (scenarioKey === "Buy Put") {
|
||||||
limits = {
|
limits = {
|
||||||
// Maximum profit when underlying goes to 0
|
maxProfit: `$${(leg.strike * 100 - totalPremium).toLocaleString(
|
||||||
maxProfit: `$${(selectedStrike * 100 - premium)?.toLocaleString(
|
|
||||||
"en-US",
|
"en-US",
|
||||||
{
|
{
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2,
|
maximumFractionDigits: 2,
|
||||||
},
|
},
|
||||||
)}`,
|
)}`,
|
||||||
maxLoss: `-$${premium?.toLocaleString("en-US", {
|
maxLoss: `-$${totalPremium.toLocaleString("en-US", {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2,
|
maximumFractionDigits: 2,
|
||||||
})}`,
|
})}`,
|
||||||
};
|
};
|
||||||
} else if (scenarioKey === "Sell Put") {
|
} else if (scenarioKey === "Sell Put") {
|
||||||
limits = {
|
limits = {
|
||||||
maxProfit: `$${premium?.toLocaleString("en-US", {
|
maxProfit: `$${totalPremium.toLocaleString("en-US", {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2,
|
maximumFractionDigits: 2,
|
||||||
})}`,
|
})}`,
|
||||||
// Maximum loss when underlying goes to 0
|
maxLoss: `-$${(leg.strike * 100 - totalPremium).toLocaleString(
|
||||||
maxLoss: `-$${(selectedStrike * 100 - premium)?.toLocaleString(
|
|
||||||
"en-US",
|
"en-US",
|
||||||
{
|
{
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
@ -230,31 +262,21 @@
|
|||||||
console.error("Limits not defined for scenario:", scenarioKey);
|
console.error("Limits not defined for scenario:", scenarioKey);
|
||||||
limits = { maxProfit: "n/a", maxLoss: "n/a" };
|
limits = { maxProfit: "n/a", maxLoss: "n/a" };
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataPoints = [];
|
|
||||||
const xMin = 0;
|
|
||||||
const xMax = Math.floor(Math.max(currentStockPrice, selectedStrike) * 3);
|
|
||||||
const step = 10;
|
|
||||||
|
|
||||||
if (payoffFunctions[scenarioKey]) {
|
|
||||||
for (let s = xMin; s <= xMax; s += step) {
|
|
||||||
// For each price point, calculate payoff based on the scenario.
|
|
||||||
const payoff = payoffFunctions[scenarioKey](s, selectedStrike, premium);
|
|
||||||
dataPoints.push([s, payoff]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
// For multiple legs, simply display the aggregated premium info
|
||||||
"Payoff function not implemented for scenario:",
|
limits = {
|
||||||
scenarioKey,
|
info: `Aggregated Premium: $${totalPremium.toLocaleString("en-US", {
|
||||||
);
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build the chart options (using the first leg's ticker for the title)
|
||||||
const options = {
|
const options = {
|
||||||
credits: {
|
credits: { enabled: false },
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
chart: {
|
chart: {
|
||||||
type: "area", // or "line"
|
type: "area",
|
||||||
backgroundColor: $mode === "light" ? "#fff" : "#09090B",
|
backgroundColor: $mode === "light" ? "#fff" : "#09090B",
|
||||||
plotBackgroundColor: $mode === "light" ? "#fff" : "#09090B",
|
plotBackgroundColor: $mode === "light" ? "#fff" : "#09090B",
|
||||||
height: 400,
|
height: 400,
|
||||||
@ -272,9 +294,7 @@
|
|||||||
text: `${selectedTicker} Price at Expiration ($)`,
|
text: `${selectedTicker} Price at Expiration ($)`,
|
||||||
style: { color: $mode === "light" ? "#545454" : "white" },
|
style: { color: $mode === "light" ? "#545454" : "white" },
|
||||||
},
|
},
|
||||||
labels: {
|
labels: { style: { color: $mode === "light" ? "#545454" : "white" } },
|
||||||
style: { color: $mode === "light" ? "#545454" : "white" },
|
|
||||||
},
|
|
||||||
plotLines: [
|
plotLines: [
|
||||||
// Underlying Price line
|
// Underlying Price line
|
||||||
{
|
{
|
||||||
@ -288,22 +308,27 @@
|
|||||||
},
|
},
|
||||||
zIndex: 5,
|
zIndex: 5,
|
||||||
},
|
},
|
||||||
{
|
// Only add a breakeven line if there is a single leg
|
||||||
|
breakEvenPrice !== null
|
||||||
|
? {
|
||||||
value: breakEvenPrice,
|
value: breakEvenPrice,
|
||||||
color: "#10B981",
|
color: "#10B981",
|
||||||
dashStyle: "Dash",
|
dashStyle: "Dash",
|
||||||
width: $screenWidth < 640 ? 0 : 1.5,
|
width: $screenWidth < 640 ? 0 : 1.5,
|
||||||
label: {
|
label: {
|
||||||
text: `<span class="hidden sm:block text-black dark:text-white text-sm">Breakeven $${breakEvenPrice.toFixed(2)}</span>`,
|
text: `<span class="hidden sm:block text-black dark:text-white text-sm">Breakeven $${breakEvenPrice.toFixed(
|
||||||
|
2,
|
||||||
|
)}</span>`,
|
||||||
style: { color: $mode === "light" ? "black" : "white" },
|
style: { color: $mode === "light" ? "black" : "white" },
|
||||||
},
|
},
|
||||||
zIndex: 5,
|
zIndex: 5,
|
||||||
},
|
}
|
||||||
],
|
: null,
|
||||||
|
].filter((line) => line !== null),
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
title: {
|
title: {
|
||||||
text: "Expected Profit/Loss ($)",
|
text: "<span class='hidden sm:block'>Expected Profit/Loss ($)</span>",
|
||||||
style: { color: $mode === "light" ? "#545454" : "white" },
|
style: { color: $mode === "light" ? "#545454" : "white" },
|
||||||
},
|
},
|
||||||
gridLineWidth: 1,
|
gridLineWidth: 1,
|
||||||
@ -318,24 +343,17 @@
|
|||||||
tooltip: {
|
tooltip: {
|
||||||
shared: true,
|
shared: true,
|
||||||
useHTML: true,
|
useHTML: true,
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.8)", // Semi-transparent black
|
backgroundColor: "rgba(0, 0, 0, 0.8)",
|
||||||
borderColor: "rgba(255, 255, 255, 0.2)", // Slightly visible white border
|
borderColor: "rgba(255, 255, 255, 0.2)",
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
style: {
|
style: { color: "#fff", fontSize: "16px", padding: "10px" },
|
||||||
color: "#fff",
|
|
||||||
fontSize: "16px",
|
|
||||||
padding: "10px",
|
|
||||||
},
|
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
formatter: function () {
|
formatter: function () {
|
||||||
const underlyingPrice = this.x;
|
const underlyingPrice = this.x;
|
||||||
const profitLoss = this.y;
|
const profitLoss = this.y;
|
||||||
// Calculate percentage change for underlying price relative to currentStockPrice
|
|
||||||
const underlyingPctChange =
|
const underlyingPctChange =
|
||||||
((underlyingPrice - currentStockPrice) / currentStockPrice) * 100;
|
((underlyingPrice - currentStockPrice) / currentStockPrice) * 100;
|
||||||
// Calculate profit/loss percentage relative to the total premium paid
|
const profitLossPctChange = (profitLoss / totalPremium) * 100;
|
||||||
const profitLossPctChange = (profitLoss / premium) * 100;
|
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="flex flex-col items-start text-sm">
|
<div class="flex flex-col items-start text-sm">
|
||||||
<div>
|
<div>
|
||||||
@ -352,33 +370,28 @@
|
|||||||
`;
|
`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
plotOptions: {
|
plotOptions: {
|
||||||
area: {
|
area: {
|
||||||
fillOpacity: 0.2,
|
fillOpacity: 0.2,
|
||||||
marker: {
|
marker: { enabled: false },
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
animation: false,
|
animation: false,
|
||||||
},
|
},
|
||||||
series: {
|
series: {
|
||||||
zoneAxis: "y",
|
zoneAxis: "y",
|
||||||
zones: [
|
zones: [
|
||||||
{
|
{
|
||||||
value: 0, // below $0 -> red
|
value: 0,
|
||||||
color: "#E02424",
|
color: "#E02424",
|
||||||
fillColor: "rgba(224,36,36,0.5)",
|
fillColor: "rgba(224,36,36,0.5)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: "#10B981", // above $0 -> green
|
color: "#10B981",
|
||||||
fillColor: "rgba(16,185,129,0.5)",
|
fillColor: "rgba(16,185,129,0.5)",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: { enabled: false },
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: "Payoff",
|
name: "Payoff",
|
||||||
@ -432,8 +445,6 @@
|
|||||||
} else {
|
} else {
|
||||||
selectedAction = "Buy";
|
selectedAction = "Buy";
|
||||||
}
|
}
|
||||||
|
|
||||||
config = plotData();
|
|
||||||
shouldUpdate = true;
|
shouldUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,7 +460,6 @@
|
|||||||
// Set a new debounce timeout (1 second)
|
// Set a new debounce timeout (1 second)
|
||||||
debounceTimeout = setTimeout(() => {
|
debounceTimeout = setTimeout(() => {
|
||||||
config = plotData();
|
config = plotData();
|
||||||
shouldUpdate = true;
|
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +476,6 @@
|
|||||||
// Set a new debounce timeout (1 second)
|
// Set a new debounce timeout (1 second)
|
||||||
debounceTimeout = setTimeout(() => {
|
debounceTimeout = setTimeout(() => {
|
||||||
config = plotData();
|
config = plotData();
|
||||||
shouldUpdate = true;
|
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,10 +528,7 @@
|
|||||||
const output = await getContractHistory(optionSymbol);
|
const output = await getContractHistory(optionSymbol);
|
||||||
|
|
||||||
selectedOptionPrice = output?.history?.at(-1)?.mark;
|
selectedOptionPrice = output?.history?.at(-1)?.mark;
|
||||||
|
|
||||||
config = plotData();
|
|
||||||
shouldUpdate = true;
|
shouldUpdate = true;
|
||||||
isLoaded = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getStockData() {
|
async function getStockData() {
|
||||||
@ -557,10 +563,12 @@
|
|||||||
|
|
||||||
await getStockData();
|
await getStockData();
|
||||||
await loadData("default");
|
await loadData("default");
|
||||||
|
inputValue = "";
|
||||||
}
|
}
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await getStockData();
|
await getStockData();
|
||||||
await loadData("default");
|
await loadData("default");
|
||||||
|
shouldUpdate = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
@ -570,19 +578,10 @@
|
|||||||
$: {
|
$: {
|
||||||
if (shouldUpdate) {
|
if (shouldUpdate) {
|
||||||
shouldUpdate = false;
|
shouldUpdate = false;
|
||||||
userStrategy = [
|
|
||||||
{
|
|
||||||
ticker: selectedTicker,
|
|
||||||
action: selectedAction,
|
|
||||||
quantity: selectedQuantity,
|
|
||||||
date: selectedDate,
|
|
||||||
strike: selectedStrike,
|
|
||||||
optionType: selectedOptionType,
|
|
||||||
optionPrice: selectedOptionPrice,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
console.log("yes");
|
config = plotData();
|
||||||
|
|
||||||
|
isLoaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,6 +655,51 @@
|
|||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
{#if isLoaded && config}
|
{#if isLoaded && config}
|
||||||
|
<Combobox.Root
|
||||||
|
items={searchBarData}
|
||||||
|
bind:inputValue
|
||||||
|
bind:touchedInput
|
||||||
|
>
|
||||||
|
<div class="relative w-full">
|
||||||
|
<Combobox.Input
|
||||||
|
on:input={search}
|
||||||
|
class="mb-3 text-sm controls-input bg-white dark:bg-default focus:outline-hidden border border-gray-300 dark:border-gray-500 rounded placeholder:text-gray-600 dark:placeholder:text-gray-200 px-2 py-1.5 grow w-full max-w-48"
|
||||||
|
placeholder="Search Ticker"
|
||||||
|
aria-label="Search Ticker"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{#if inputValue?.length !== 0 && inputValue !== selectedTicker}
|
||||||
|
<Combobox.Content
|
||||||
|
class=" z-10 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-default px-1 py-3 shadow-sm outline-hidden"
|
||||||
|
sideOffset={8}
|
||||||
|
>
|
||||||
|
{#each searchBarData as searchItem}
|
||||||
|
<Combobox.Item
|
||||||
|
class="cursor-pointer border-b border-gray-300 dark:border-gray-500 last:border-none flex h-fit w-auto select-none items-center rounded-button py-1 px-2 text-sm capitalize outline-hidden transition-all duration-75 data-highlighted:bg-gray-200 dark:data-highlighted:bg-primary"
|
||||||
|
value={searchItem?.symbol}
|
||||||
|
label={searchItem?.symbol}
|
||||||
|
on:click={(e) => changeTicker(searchItem)}
|
||||||
|
>
|
||||||
|
<div class="flex flex-col items-start">
|
||||||
|
<span
|
||||||
|
class="text-sm text-blue-700 dark:text-blue-400"
|
||||||
|
>{searchItem?.symbol}</span
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-xs sm:text-sm text-muted dark:text-white"
|
||||||
|
>{searchItem?.name}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</Combobox.Item>
|
||||||
|
{:else}
|
||||||
|
<span class="block px-5 py-2 text-sm">
|
||||||
|
No results found
|
||||||
|
</span>
|
||||||
|
{/each}
|
||||||
|
</Combobox.Content>
|
||||||
|
{/if}
|
||||||
|
</Combobox.Root>
|
||||||
|
|
||||||
<!-- Table container -->
|
<!-- Table container -->
|
||||||
<div
|
<div
|
||||||
class="overflow-x-auto border border-gray-300 dark:border-gray-600 rounded"
|
class="overflow-x-auto border border-gray-300 dark:border-gray-600 rounded"
|
||||||
@ -722,50 +766,7 @@
|
|||||||
{#each userStrategy as item}
|
{#each userStrategy as item}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-4 py-3 whitespace-nowrap font-semibold">
|
<td class="px-4 py-3 whitespace-nowrap font-semibold">
|
||||||
<Combobox.Root
|
{selectedTicker}
|
||||||
items={searchBarData}
|
|
||||||
bind:inputValue
|
|
||||||
bind:touchedInput
|
|
||||||
>
|
|
||||||
<div class="relative w-full">
|
|
||||||
<Combobox.Input
|
|
||||||
on:input={search}
|
|
||||||
class="text-sm controls-input bg-white dark:bg-[#2A2E39] focus:outline-hidden border border-gray-300 dark:border-gray-500 rounded placeholder:text-gray-600 dark:placeholder:text-gray-200 px-2 py-1.5 grow w-full min-w-54"
|
|
||||||
placeholder="Search Ticker"
|
|
||||||
aria-label="Search Ticker"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{#if inputValue?.length !== 0 && inputValue !== item?.ticker}
|
|
||||||
<Combobox.Content
|
|
||||||
class=" z-10 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-default px-1 py-3 shadow-sm outline-hidden"
|
|
||||||
sideOffset={8}
|
|
||||||
>
|
|
||||||
{#each searchBarData as searchItem}
|
|
||||||
<Combobox.Item
|
|
||||||
class="cursor-pointer border-b border-gray-300 dark:border-gray-500 last:border-none flex h-fit w-auto select-none items-center rounded-button py-3 pl-5 pr-1.5 text-sm capitalize outline-hidden transition-all duration-75 data-highlighted:bg-gray-200 dark:data-highlighted:bg-primary"
|
|
||||||
value={searchItem?.symbol}
|
|
||||||
label={searchItem?.symbol}
|
|
||||||
on:click={(e) => changeTicker(searchItem)}
|
|
||||||
>
|
|
||||||
<div class="flex flex-col items-start">
|
|
||||||
<span
|
|
||||||
class="text-sm text-blue-700 dark:text-blue-400"
|
|
||||||
>{searchItem?.symbol}</span
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="text-xs sm:text-sm text-muted dark:text-white"
|
|
||||||
>{searchItem?.name}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</Combobox.Item>
|
|
||||||
{:else}
|
|
||||||
<span class="block px-5 py-2 text-sm">
|
|
||||||
No results found
|
|
||||||
</span>
|
|
||||||
{/each}
|
|
||||||
</Combobox.Content>
|
|
||||||
{/if}
|
|
||||||
</Combobox.Root>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 whitespace-nowrap">
|
<td class="px-4 py-3 whitespace-nowrap">
|
||||||
<label
|
<label
|
||||||
@ -930,14 +931,24 @@
|
|||||||
<div
|
<div
|
||||||
class="border border-gray-300 dark:border-gray-800 rounded-lg p-4 mb-6 shadow-sm max-w-sm"
|
class="border border-gray-300 dark:border-gray-800 rounded-lg p-4 mb-6 shadow-sm max-w-sm"
|
||||||
>
|
>
|
||||||
<div>{selectedStrategy}</div>
|
{#each userStrategy as item}
|
||||||
<div class="text-green-800 dark:text-white font-semibold">
|
<div>
|
||||||
{selectedAction?.toUpperCase()} +{selectedQuantity}
|
{userStrategy?.length > 2
|
||||||
{selectedTicker}
|
? "Custom Strategy"
|
||||||
{formatDate(selectedDate)}
|
: selectedStrategy}
|
||||||
{selectedStrike}
|
|
||||||
{selectedOptionType} @${selectedOptionPrice}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="{item?.action === 'Buy'
|
||||||
|
? 'text-green-800'
|
||||||
|
: 'text-red-800'} dark:text-white font-semibold"
|
||||||
|
>
|
||||||
|
{item?.action?.toUpperCase()} +{item?.quantity}
|
||||||
|
{selectedTicker}
|
||||||
|
{formatDate(item?.date)}
|
||||||
|
{item?.strike}
|
||||||
|
{item?.optionType} @${item?.optionPrice}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Stock Section -->
|
<!-- Stock Section -->
|
||||||
@ -999,7 +1010,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-baseline">
|
<div class="flex items-baseline">
|
||||||
<span class="text-lg font-semibold"
|
<span class="text-lg font-semibold"
|
||||||
>${premium?.toLocaleString("en-US", {
|
>${totalPremium?.toLocaleString("en-US", {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2,
|
maximumFractionDigits: 2,
|
||||||
})}
|
})}
|
||||||
@ -1043,398 +1054,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--
|
|
||||||
<h2 class="text-xl font-bold text-gray-800 dark:text-white 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 dark:text-white">
|
|
||||||
Probability of Profit (PoP)
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Probability of Max Profit
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Probability of Max Loss
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white 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 dark:text-white">
|
|
||||||
Expected Value (EV)
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Expected Return (EV/risk)
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Reward/Risk
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white mb-4 flex items-center"
|
|
||||||
>
|
|
||||||
Position Greeks
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Delta (Δ)
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Gamma (Γ)
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Theta (Θ)
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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 dark:text-white">
|
|
||||||
Vega (v)
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 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>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex justify-center items-center h-80">
|
<div class="flex justify-center items-center h-80">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user