From 441902dca7fa7fef33c2d8f2c98f0ce2274616a8 Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Tue, 8 Apr 2025 14:00:45 +0200 Subject: [PATCH] upgrade daisyui && update calculator --- package-lock.json | 8 +- package.json | 2 +- src/routes/options-calculator/+page.svelte | 164 ++++++++++++--------- 3 files changed, 97 insertions(+), 77 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8fb5f94c..611d6c6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "clsx": "^2.1.1", "cmdk-sv": "^0.0.18", "compression": "^1.7.4", - "daisyui": "^5.0.12", + "daisyui": "^5.0.16", "date-fns": "^3.6.0", "date-fns-tz": "^3.1.3", "date-picker-svelte": "^2.12.0", @@ -4043,9 +4043,9 @@ "license": "BSD-3-Clause" }, "node_modules/daisyui": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.12.tgz", - "integrity": "sha512-01DU0eYBcHgPtuf5fxcrkGkIN6/Uyaqmkle5Yo3ZyW9YVAu036ALZbjv2KH5euvUbeQ4r9q3gAarGcf7Tywhng==", + "version": "5.0.16", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.16.tgz", + "integrity": "sha512-MQiZQ21+r91zrKv3fxDOF56dzkfrr2FyXOaR/1T4f9AIeI/ilkc0i+UqOIE/VqjIfkWyq+wBPmBcyIf6iPJpYQ==", "dev": true, "license": "MIT", "funding": { diff --git a/package.json b/package.json index dfed26b8..2a44a80e 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "clsx": "^2.1.1", "cmdk-sv": "^0.0.18", "compression": "^1.7.4", - "daisyui": "^5.0.12", + "daisyui": "^5.0.16", "date-fns": "^3.6.0", "date-fns-tz": "^3.1.3", "date-picker-svelte": "^2.12.0", diff --git a/src/routes/options-calculator/+page.svelte b/src/routes/options-calculator/+page.svelte index ec36986f..265a565c 100644 --- a/src/routes/options-calculator/+page.svelte +++ b/src/routes/options-calculator/+page.svelte @@ -14,27 +14,6 @@ import { mode } from "mode-watcher"; import highcharts from "$lib/highcharts.ts"; - // Types - type Strategy = { - name: string; - sentiment: string; - description: string; - }; - - type OptionLeg = { - action: string; - quantity: number; - date: string; - strike: number; - optionType: string; - optionPrice: number; - }; - - type SearchResult = { - symbol: string; - type: string; - }; - export let data; // State variables with proper types @@ -68,13 +47,13 @@ let rawData: Record = {}; // Search variables - let searchBarData: SearchResult[] = []; + let searchBarData = []; let timeoutId: ReturnType; let inputValue = ""; let touchedInput = false; // Strategy definitions - const prebuiltStrategy: Strategy[] = [ + const prebuiltStrategy = [ { name: "Long Call", sentiment: "Bullish", @@ -99,6 +78,18 @@ description: "In this strategy, an investor sells a put option, expecting that the price of the underlying asset will remain stable or increase, allowing the investor to keep the premium received from selling the option. Investors typically use a short put strategy when they have a neutral to bullish outlook on the stock and and views a potential assignment as an opportunity to buy the asset at a desirable price.", }, + { + name: "Cash Secured Put", + sentiment: "Bullish", + description: + "In this strategy, an investor sells a put option and simultaneously sets aside enough cash to buy the stock. The goal is to be assigned the stock at a desirable price and generate income from the option premium. Investors typically use a cash secured put strategy when they have a neutral to bullish outlook on the stock and view a potential assignment as an opportunity to buy the asset at a desirable price.", + }, + { + name: "Bull Call Spread", + sentiment: "Bullish", + description: + "In this strategy, an investor simultaneously purchases call options at a specific strike price and sells the same number of calls at a higher strike price. Both call options have the same expiration date. This strategy is used when the investor is bullish and expects a moderate rise in the price of the underlying asset. The investor limits their upside profit potential but reduces the net premium spent compared to buying a single call option outright. The strategy is also known as a 'debit call spread' because the investor pays a net debit to establish the position.", + }, // Other strategies commented out in original code ]; @@ -107,7 +98,7 @@ // STRATEGY FUNCTIONS - async function changeStrategy(strategy: Strategy) { + async function changeStrategy(strategy) { selectedStrategy = strategy?.name; description = strategy?.description; @@ -129,21 +120,47 @@ selectedOptionType = "Put"; selectedAction = "Sell"; break; + case "Cash Secured Put": + selectedOptionType = "Put"; + selectedAction = "Sell"; + break; default: console.warn("Unknown strategy:", strategy); selectedOptionType = null; selectedAction = null; } - userStrategy = [ - { - strike: selectedStrike, - optionType: selectedOptionType, - date: selectedDate, - optionPrice: selectedOptionPrice, - quantity: selectedQuantity, - action: selectedAction, - }, - ]; + if (["Bull Call Spread"]?.includes(selectedStrategy)) { + userStrategy = [ + { + strike: selectedStrike, + optionType: "Call", + date: selectedDate, + optionPrice: selectedOptionPrice, + quantity: 1, + action: "Buy", + }, + { + strike: selectedStrike, + optionType: "Call", + date: selectedDate, + optionPrice: selectedOptionPrice, + quantity: 1, + action: "Sell", + }, + ]; + } else { + userStrategy = [ + { + strike: selectedStrike, + optionType: selectedOptionType, + date: selectedDate, + optionPrice: selectedOptionPrice, + quantity: selectedQuantity, + action: selectedAction, + }, + ]; + } + shouldUpdate = true; } @@ -500,7 +517,7 @@ } }; - async function loadData(state: string) { + async function loadData() { if (!rawData?.getData) { console.error("rawData is undefined or invalid in loadData"); return; @@ -525,17 +542,16 @@ item.strikeList = strikeList; // Find closest strike to current stock price - if (!strikeList.includes(selectedStrike) && strikeList.length > 0) { + if (!strikeList?.includes(item?.strike) && strikeList?.length > 0) { selectedStrike = strikeList.reduce((closest, strike) => { return Math.abs(strike - currentStockPrice) < Math.abs(closest - currentStockPrice) ? strike : closest; }, strikeList[0]); + item.strike = selectedStrike; } - item.strike = selectedStrike; - // Get option price optionSymbol = buildOptionSymbol( selectedTicker, @@ -547,6 +563,8 @@ const output = await getContractHistory(optionSymbol); selectedOptionPrice = output?.history?.at(-1)?.mark || 0; item.optionPrice = selectedOptionPrice; + item.optionSymbol = optionSymbol; + item.optionType = selectedOptionType; } } else { optionData = rawData?.getData[selectedOptionType] || {}; @@ -581,22 +599,20 @@ selectedOptionPrice = output?.history?.at(-1)?.mark || 0; // Update user strategy if necessary - if (state === "default") { - userStrategy = [ - { - date: selectedDate, - strike: selectedStrike, - optionType: selectedOptionType, - optionPrice: selectedOptionPrice, - action: selectedAction, - quantity: selectedQuantity, - strikeList: strikeList, - dateList: dateList, - }, - ]; - } + userStrategy = [ + { + date: selectedDate, + strike: selectedStrike, + optionType: selectedOptionType, + optionPrice: selectedOptionPrice, + action: selectedAction, + quantity: selectedQuantity, + strikeList: strikeList, + dateList: dateList, + optionSymbol: optionSymbol, + }, + ]; } - shouldUpdate = true; } catch (error) { console.error("Error loading data:", error); @@ -644,6 +660,7 @@ const newLeg = { ...lastLeg }; // Create a shallow copy userStrategy = [...userStrategy, newLeg]; } + await loadData(); shouldUpdate = true; } @@ -675,6 +692,7 @@ // Update the selectedAction (for new legs) selectedOptionType = selectedOptionType === "Call" ? "Put" : "Call"; } + await loadData(); shouldUpdate = true; } @@ -699,7 +717,7 @@ const updatedStrategy = [...userStrategy]; updatedStrategy[index].date = selectedDate; userStrategy = updatedStrategy; - await loadData("default"); + await loadData(); shouldUpdate = true; } } @@ -710,11 +728,12 @@ const updatedStrategy = [...userStrategy]; updatedStrategy[index].strike = selectedStrike; userStrategy = updatedStrategy; + await loadData(); shouldUpdate = true; } } - function handleOptionPriceInput(event: Event, index) { + async function handleOptionPriceInput(event: Event, index) { const value = (event.target as HTMLInputElement).value; selectedOptionPrice = value === "" ? null : +value; @@ -726,12 +745,12 @@ if (debounceTimeout) clearTimeout(debounceTimeout); // Set a new debounce timeout - debounceTimeout = setTimeout(() => { + debounceTimeout = setTimeout(async () => { shouldUpdate = true; }, 300); } - function handleQuantityInput(event, index) { + async function handleQuantityInput(event, index) { if (index !== undefined && userStrategy[index]) { const value = (event.target as HTMLInputElement).value; @@ -742,7 +761,7 @@ if (debounceTimeout) clearTimeout(debounceTimeout); // Set a new debounce timeout - debounceTimeout = setTimeout(() => { + debounceTimeout = setTimeout(async () => { shouldUpdate = true; }, 300); } @@ -775,14 +794,14 @@ }, 50); // delay } - async function changeTicker(data: SearchResult) { + async function changeTicker(data) { if (!data?.symbol) return; selectedTicker = data.symbol; assetType = data?.type?.toLowerCase() || "stocks"; await getStockData(); - await loadData("default"); + await loadData(); inputValue = ""; shouldUpdate = true; } @@ -791,7 +810,7 @@ onMount(async () => { await getStockData(); - await loadData("default"); + await loadData(); shouldUpdate = true; }); @@ -881,6 +900,7 @@ {/each} +

{selectedStrategy} @@ -945,7 +965,7 @@ > - + {#each userStrategy as item, index} - + {selectedTicker} - + - + - +