From 64377864219cbb0f533f2a7dd4e1999345ce64df Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Thu, 13 Jun 2024 15:37:16 +0200 Subject: [PATCH] reduce loading time for historical price --- src/lib/components/Searchbar.svelte | 6 +- .../crypto/[tickerID]/+layout.server.ts | 3 - src/routes/crypto/[tickerID]/+page.svelte | 110 +++- src/routes/etf/[tickerID]/+layout.server.ts | 3 + src/routes/etf/[tickerID]/+page.svelte | 581 +++++++++--------- .../stocks/[tickerID]/+layout.server.ts | 3 - src/routes/stocks/[tickerID]/+page.svelte | 360 ++++++----- 7 files changed, 580 insertions(+), 486 deletions(-) diff --git a/src/lib/components/Searchbar.svelte b/src/lib/components/Searchbar.svelte index 495c64e1..26c19c76 100644 --- a/src/lib/components/Searchbar.svelte +++ b/src/lib/components/Searchbar.svelte @@ -232,13 +232,17 @@ function handleKeyDown(event) { -const handleControlF = (event) => { +const handleControlF = async (event) => { + if (event.ctrlKey && event.key === 'k') { // Ctrl+F is pressed, open the modal const keyboardSearch = document.getElementById('searchBarModal'); keyboardSearch?.dispatchEvent(new MouseEvent('click')) event.preventDefault() + await loadSearchData(); + + } }; diff --git a/src/routes/crypto/[tickerID]/+layout.server.ts b/src/routes/crypto/[tickerID]/+layout.server.ts index f1d6fad6..b448ef38 100644 --- a/src/routes/crypto/[tickerID]/+layout.server.ts +++ b/src/routes/crypto/[tickerID]/+layout.server.ts @@ -85,7 +85,6 @@ export const load = async ({ params, locals, setHeaders}) => { fetchData(apiURL,'/stock-quote',params.tickerID), fetchData(apiURL,'/stock-rating',params.tickerID), fetchData(apiURL,'/value-at-risk',params.tickerID), - fetchData(apiURL,'/historical-price',params.tickerID), fetchData(apiURL,'/one-day-price',params.tickerID), fetchWatchlist(fastifyURL, locals?.user?.id), fetchPortfolio(fastifyURL, locals?.user?.id) @@ -96,7 +95,6 @@ export const load = async ({ params, locals, setHeaders}) => { getStockQuote, getStockTARating, getVaR, - getHistoricalPrice, getOneDayPrice, getUserWatchlist, getUserPortfolio, @@ -113,7 +111,6 @@ export const load = async ({ params, locals, setHeaders}) => { getStockQuote, getStockTARating, getVaR, - getHistoricalPrice, getOneDayPrice, getUserWatchlist, getUserPortfolio, diff --git a/src/routes/crypto/[tickerID]/+page.svelte b/src/routes/crypto/[tickerID]/+page.svelte index a6d86524..503311db 100644 --- a/src/routes/crypto/[tickerID]/+page.svelte +++ b/src/routes/crypto/[tickerID]/+page.svelte @@ -3,8 +3,8 @@ import {AreaSeries, Chart, PriceLine, CandlestickSeries} from 'svelte-lightweight-charts'; import { TrackingModeExitMode } from 'lightweight-charts'; - import {screenWidth, displayCompanyName, numberOfUnreadNotification, globalForm, userRegion, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, clientSideCache, cryptoTicker} from '$lib/store'; - import { onDestroy, onMount, afterUpdate } from 'svelte'; + import {setCache, getCache, screenWidth, displayCompanyName, numberOfUnreadNotification, globalForm, userRegion, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, clientSideCache, cryptoTicker} from '$lib/store'; + import { onDestroy, onMount } from 'svelte'; import CryptoKeyInformation from '$lib/components/CryptoKeyInformation.svelte'; import Lazy from '$lib/components/Lazy.svelte'; @@ -24,10 +24,8 @@ export let data; export let form; - let isLoaded = false; let displayChartType = 'line'; - let pricePrediction = data?.getPricePrediction ?? []; let cryptoProfile = data?.getStockDeck ?? []; let previousClose = data?.getStockQuote?.previousClose; @@ -188,6 +186,7 @@ $: { break; case '1W': displayData = '1W'; + await historicalPrice('one-week'); if(oneWeekPrice?.length !== 0) { displayLastLogicalRangeValue = oneWeekPrice?.at(0)?.close; @@ -204,6 +203,7 @@ $: { break; case '1M': displayData = '1M'; + await historicalPrice('one-month'); if(oneMonthPrice?.length !== 0) { displayLastLogicalRangeValue = oneMonthPrice?.at(0)?.close; @@ -219,6 +219,7 @@ $: { case '6M': displayData = '6M'; + await historicalPrice('six-months'); if(sixMonthPrice?.length !== 0) { displayLastLogicalRangeValue = sixMonthPrice?.at(0)?.close; @@ -233,6 +234,7 @@ $: { break; case '1Y': displayData = '1Y'; + await historicalPrice('one-year'); if(oneYearPrice?.length !== 0) { displayLastLogicalRangeValue = oneYearPrice?.at(0)?.close; @@ -246,6 +248,7 @@ $: { break; case 'MAX': displayData = 'MAX'; + await historicalPrice('max'); if(threeYearPrice?.length !== 0) { displayLastLogicalRangeValue = threeYearPrice?.at(0)?.close; @@ -289,11 +292,89 @@ $: { let oneYearPrice = []; let threeYearPrice = []; - let pastPriceList = []; + async function historicalPrice(timePeriod:string) { + const cachedData = getCache($cryptoTicker, 'historicalPrice'+timePeriod); + if (cachedData) { + switch (timePeriod) { + case 'one-week': + oneWeekPrice = cachedData + break; + case 'one-month': + oneMonthPrice = cachedData + break; + case 'six-months': + sixMonthPrice = cachedData + break; + case 'one-year': + oneYearPrice = cachedData + break; + case 'max': + threeYearPrice = cachedData + break; + default: + console.log(`Unsupported time period: ${timePeriod}`); + } + } else { + output = null; + + const postData = { + ticker: $cryptoTicker, + timePeriod: timePeriod, + }; + + const response = await fetch(apiURL+'/historical-price', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(postData) + }); + + output = await response?.json() ?? []; + + const mapData = (data) => data?.map(({ time, open, high, low, close }) => ({ + time: Date.parse(time), + open, + high, + low, + close + })); + + const mappedData = mapData(output); + try { + switch (timePeriod) { + case 'one-week': + oneWeekPrice = mappedData + break; + case 'one-month': + oneMonthPrice = mappedData + break; + case 'six-months': + sixMonthPrice = mappedData + break; + case 'one-year': + oneYearPrice = mappedData + break; + case 'max': + threeYearPrice = mappedData + break; + default: + console.log(`Unsupported time period: ${timePeriod}`); + } + setCache($cryptoTicker, mappedData, 'historicalPrice'+timePeriod); + + } catch (e) { + console.log(e); + } + + } +} + + async function initializePrice() { output = null; @@ -304,19 +385,9 @@ $: { try { output = [...data?.getOneDayPrice] ?? []; - oneDayPrice = data?.getOneDayPrice; - pastPriceList = data?.getHistoricalPrice; - oneDayPrice = output?.map(item => ({ time: Date.parse(item?.time), open: item?.open !== null ? item?.open : NaN, high: item?.high !== null ? item?.high : NaN, low: item?.low !== null ? item?.low : NaN, close: item?.close !== null ? item?.close : NaN})); - oneWeekPrice = pastPriceList['1W']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneMonthPrice = pastPriceList['1M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneMonthPrice = Object?.values(oneMonthPrice?.reduce((acc, cur) => Object?.assign(acc, {[cur?.time]: cur}), {})); - - sixMonthPrice = pastPriceList['6M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneYearPrice = pastPriceList['1Y']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - threeYearPrice = pastPriceList['MAX']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - + displayData = oneDayPrice?.length === 0 && sixMonthPrice?.length !== 0 ? '6M' : '1D'; //lastValue = oneDayPrice[oneDayPrice?.length - 1]?.value; if (displayData === '1D') @@ -573,14 +644,12 @@ function changeChartType() { if ($cryptoTicker && typeof window !== 'undefined') // add a check to see if running on client-side { $realtimePrice = null; - isLoaded = false; dowloadData = false; oneDayPrice = []; oneWeekPrice = []; oneMonthPrice = []; oneYearPrice = []; threeYearPrice = []; - pastPriceList = []; taRating = {}; varDict={} output = null; @@ -593,18 +662,15 @@ function changeChartType() { const asyncFunctions = []; - Promise.all(asyncFunctions) .then((results) => { initializePrice() - isLoaded = true; }) .catch((error) => { console.error('An error occurred:', error); }); - isLoaded = true; } @@ -773,7 +839,7 @@ afterUpdate(async () => { - {#if output !== null && pastPriceList?.length !== 0} + {#if output !== null}
{#if displayData === '1D' && oneDayPrice?.length === 0}

diff --git a/src/routes/etf/[tickerID]/+layout.server.ts b/src/routes/etf/[tickerID]/+layout.server.ts index 4a3de150..3da19c07 100644 --- a/src/routes/etf/[tickerID]/+layout.server.ts +++ b/src/routes/etf/[tickerID]/+layout.server.ts @@ -115,6 +115,7 @@ const promises = [ fetchData(apiURL,'/options-bubble',params.tickerID), fetchData(apiURL,'/wiim',params.tickerID), fetchData(apiURL,'/value-at-risk',params.tickerID), + fetchData(apiURL,'/one-day-price',params.tickerID), fetchWatchlist(fastifyURL, locals?.user?.id), fetchPortfolio(fastifyURL, locals?.user?.id) ]; @@ -131,6 +132,7 @@ const promises = [ getOptionsData, getWhyPriceMoved, getVaR, + getOneDayPrice, getUserWatchlist, getUserPortfolio, ] = await Promise.all(promises); @@ -153,6 +155,7 @@ const promises = [ getOptionsData, getWhyPriceMoved, getVaR, + getOneDayPrice, getUserWatchlist, getUserPortfolio, companyName, diff --git a/src/routes/etf/[tickerID]/+page.svelte b/src/routes/etf/[tickerID]/+page.svelte index 8f192baf..72fbded7 100644 --- a/src/routes/etf/[tickerID]/+page.svelte +++ b/src/routes/etf/[tickerID]/+page.svelte @@ -3,7 +3,7 @@ import {AreaSeries, Chart, PriceLine, CandlestickSeries} from 'svelte-lightweight-charts'; import { TrackingModeExitMode } from 'lightweight-charts'; - import {trendAnalysisComponent, priceAnalysisComponent, assetType, screenWidth, globalForm, userRegion, numberOfUnreadNotification, displayCompanyName, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, clientSideCache, etfTicker, isOpen, isBeforeMarketOpen, isWeekend} from '$lib/store'; + import {getCache, setCache, trendAnalysisComponent, priceAnalysisComponent, assetType, screenWidth, globalForm, userRegion, numberOfUnreadNotification, displayCompanyName, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, clientSideCache, etfTicker, isOpen, isBeforeMarketOpen, isWeekend} from '$lib/store'; import { onDestroy, onMount } from 'svelte'; import ETFKeyInformation from '$lib/components/ETFKeyInformation.svelte'; import Lazy from '$lib/components/Lazy.svelte'; @@ -24,7 +24,23 @@ }); - let isLoaded = false; + + let output = null; + + + //====================================// + + + + let intervalId = null; + let oneDayPrice = []; + let oneWeekPrice = []; + let oneMonthPrice = []; + let sixMonthPrice = []; + + let oneYearPrice = []; + let threeYearPrice = []; + let geographicList = []; let sectorList = []; @@ -179,252 +195,252 @@ - let displayData; - let colorChange; - let topColorChange; - let bottomColorChange; - - let lastValue; - async function changeData(state) { - - switch (state) { - case '1D': - displayData = '1D'; - if(oneDayPrice?.length !== 0) - { - displayLastLogicalRangeValue = (oneDayPrice?.at(0)?.close ?? oneDayPrice?.at(0)?.value) //previousClose; - const length = oneDayPrice.length; - for (let i = length - 1; i >= 0; i--) { - if (!isNaN(oneDayPrice[i]?.close ?? oneDayPrice[i]?.value)) { - lastValue = oneDayPrice[i]?.close ?? oneDayPrice[i]?.value; - break; - } - } - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - - - break; - case '1W': - displayData = '1W'; - if(oneWeekPrice?.length !== 0) - { - displayLastLogicalRangeValue = oneWeekPrice?.at(0)?.close ?? oneWeekPrice?.at(0)?.value; - lastValue = oneWeekPrice.slice(-1)?.at(0)?.close ?? oneWeekPrice.slice(-1)?.at(0)?.value; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - - - break; - case '1M': - displayData = '1M'; - if(oneMonthPrice?.length !== 0) - { - displayLastLogicalRangeValue = oneMonthPrice?.at(0)?.close ?? oneMonthPrice?.at(0)?.value; - lastValue = oneMonthPrice.slice(-1)?.at(0)?.close ?? oneMonthPrice.slice(-1)?.at(0)?.value; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - break; - - case '6M': - displayData = '6M'; - if(sixMonthPrice?.length !== 0) - { - displayLastLogicalRangeValue = sixMonthPrice?.at(0)?.close ?? sixMonthPrice?.at(0)?.value; - lastValue = sixMonthPrice.slice(-1)?.at(0)?.close ?? sixMonthPrice.slice(-1)?.at(0)?.value; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - break; - case '1Y': - displayData = '1Y'; - if(oneYearPrice?.length !== 0) - { - displayLastLogicalRangeValue = oneYearPrice?.at(0)?.close ?? oneYearPrice?.at(0)?.value; - lastValue = oneYearPrice.slice(-1)?.at(0)?.close ?? oneYearPrice.slice(-1)?.at(0)?.value; - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - } - - break; - case 'MAX': - displayData = 'MAX'; - if(threeYearPrice?.length !== 0) - { - displayLastLogicalRangeValue = threeYearPrice?.at(0)?.close ?? threeYearPrice?.at(0)?.value; - lastValue = threeYearPrice.slice(-1)?.at(0)?.close ?? threeYearPrice.slice(-1)?.at(0)?.value; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - - break; - default: - return; - } - colorChange = lastValue < displayLastLogicalRangeValue ? "#FF2F1F" : "#10DB06"; - topColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.2)" : "rgb(16, 219, 6, 0.2)"; - bottomColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.001)" : "rgb(16, 219, 6, 0.001)"; - - fitContentChart(); - - - //trackButtonClick('Time Period: '+ state) - } - - - - let output = null; - - - //====================================// - - - - let intervalId = null; - let oneDayPrice = []; - let oneWeekPrice = []; - let oneMonthPrice = []; - let sixMonthPrice = []; - - let oneYearPrice = []; - let threeYearPrice = []; - let pastPriceList = []; - - - - async function getHistoricalPrice() { - - - if($clientSideCache[$etfTicker]?.getHistoricalPrice) - { - pastPriceList = $clientSideCache[$etfTicker]?.getHistoricalPrice; - } - else { - const postData = { ticker: $etfTicker}; - const response = await fetch(apiURL+'/historical-price', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(postData) - }); - - pastPriceList = await response.json(); - $clientSideCache[$etfTicker].getHistoricalPrice = pastPriceList; - } - - - if(displayChartType === 'line') { - oneWeekPrice = pastPriceList['1W']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - oneMonthPrice = pastPriceList['1M']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - sixMonthPrice = pastPriceList['6M']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - oneYearPrice = pastPriceList['1Y']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - threeYearPrice = pastPriceList['MAX']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - } - else if (displayChartType === 'candlestick') { - oneWeekPrice = pastPriceList['1W']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneMonthPrice = pastPriceList['1M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - sixMonthPrice = pastPriceList['6M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneYearPrice = pastPriceList['1Y']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - threeYearPrice = pastPriceList['MAX']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - - } - - }; - - - - async function getOneDayPrice() { - - output = null; - if (intervalId) { - clearInterval(intervalId); - } - intervalId = setInterval(checkChart, 0); - - - if($clientSideCache[$etfTicker]?.getOneDayPrice) +let displayData; +let colorChange; +let topColorChange; +let bottomColorChange; + +let lastValue; +async function changeData(state) { + + switch (state) { + case '1D': + displayData = '1D'; + if(oneDayPrice?.length !== 0) { - output = $clientSideCache[$etfTicker]?.getOneDayPrice; + displayLastLogicalRangeValue = oneDayPrice?.at(0)?.close; //previousClose + const length = oneDayPrice?.length; + for (let i = length - 1; i >= 0; i--) { + if (!isNaN(oneDayPrice[i]?.close)) { + lastValue = oneDayPrice[i]?.close; + break; + } + } + } else { - const postData = { ticker: $etfTicker}; - const response = await fetch(apiURL+'/one-day-price', { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + + + break; + case '1W': + displayData = '1W'; + await historicalPrice('one-week'); + if(oneWeekPrice?.length !== 0) + { + displayLastLogicalRangeValue = oneWeekPrice?.at(0)?.close; + lastValue = oneWeekPrice?.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + + + break; + case '1M': + displayData = '1M'; + await historicalPrice('one-month'); + if(oneMonthPrice?.length !== 0) + { + displayLastLogicalRangeValue = oneMonthPrice?.at(0)?.close; + lastValue = oneMonthPrice.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + break; + + case '6M': + displayData = '6M'; + await historicalPrice('six-months'); + if(sixMonthPrice?.length !== 0) + { + displayLastLogicalRangeValue = sixMonthPrice?.at(0)?.close; + lastValue = sixMonthPrice?.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + break; + case '1Y': + displayData = '1Y'; + await historicalPrice('one-year'); + if(oneYearPrice?.length !== 0) + { + displayLastLogicalRangeValue = oneYearPrice?.at(0)?.close; + lastValue = oneYearPrice.slice(-1)?.at(0)?.close; + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + } + + break; + case 'MAX': + displayData = 'MAX'; + await historicalPrice('max'); + if(threeYearPrice?.length !== 0) + { + displayLastLogicalRangeValue = threeYearPrice?.at(0)?.close; + lastValue = threeYearPrice.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + + break; + default: + return; + } + colorChange = lastValue < displayLastLogicalRangeValue ? "#FF2F1F" : "#10DB06"; + topColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.2)" : "rgb(16, 219, 6, 0.2)"; + bottomColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.001)" : "rgb(16, 219, 6, 0.001)"; + + fitContentChart(); + + + //trackButtonClick('Time Period: '+ state) +} + + + + +async function historicalPrice(timePeriod:string) { + + const cachedData = getCache($etfTicker, 'historicalPrice'+timePeriod); + if (cachedData) { + switch (timePeriod) { + case 'one-week': + oneWeekPrice = cachedData + break; + case 'one-month': + oneMonthPrice = cachedData + break; + case 'six-months': + sixMonthPrice = cachedData + break; + case 'one-year': + oneYearPrice = cachedData + break; + case 'max': + threeYearPrice = cachedData + break; + default: + console.log(`Unsupported time period: ${timePeriod}`); + } + } else { + output = null; + + const postData = { + ticker: $etfTicker, + timePeriod: timePeriod, + }; + + const response = await fetch(apiURL+'/historical-price', { method: 'POST', headers: { - 'Content-Type': 'application/json', + 'Content-Type': 'application/json', }, body: JSON.stringify(postData) - }); - - output = await response.json(); - $clientSideCache[$etfTicker].getOneDayPrice = output; - } - - if(displayChartType === 'line') { - oneDayPrice = output?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - oneDayPrice = oneDayPrice?.map(item => ({ time: item?.time, value: item?.value !== null ? item?.value : NaN })); - } - else if (displayChartType === 'candlestick') { - oneDayPrice = output?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneDayPrice = oneDayPrice?.map(item => ({ time: item?.time, open: item?.open !== null ? item?.open : NaN, high: item?.high !== null ? item?.high : NaN, low: item?.low !== null ? item?.low : NaN, close: item?.close !== null ? item?.close : NaN})); - } - - - - displayData = oneDayPrice?.length === 0 && sixMonthPrice?.length !== 0 ? '6M' : '1D'; - //lastValue = oneDayPrice[oneDayPrice.length - 1]?.value; - if (displayData === '1D') - { - const length = oneDayPrice.length; - for (let i = length - 1; i >= 0; i--) { - if (!isNaN(oneDayPrice[i]?.close ?? oneDayPrice[i]?.value)) { - lastValue = oneDayPrice[i]?.close ?? oneDayPrice[i]?.value; + }); + + output = await response?.json() ?? []; + + const mapData = (data) => data?.map(({ time, open, high, low, close }) => ({ + time: Date.parse(time), + open, + high, + low, + close + })); + + const mappedData = mapData(output); + try { + switch (timePeriod) { + case 'one-week': + oneWeekPrice = mappedData break; - } - } - } - else if (displayData === '6M') { - lastValue = sixMonthPrice?.slice(-1)?.at(0)?.value; - } - + case 'one-month': + oneMonthPrice = mappedData + break; + case 'six-months': + sixMonthPrice = mappedData + break; + case 'one-year': + oneYearPrice = mappedData + break; + case 'max': + threeYearPrice = mappedData + break; + default: + console.log(`Unsupported time period: ${timePeriod}`); + } + setCache($etfTicker, mappedData, 'historicalPrice'+timePeriod); + + } catch (e) { + console.log(e); + } + + } +} - displayLastLogicalRangeValue = oneDayPrice?.length === 0 && sixMonthPrice?.length !== 0 ? (sixMonthPrice?.at(0)?.close ?? sixMonthPrice?.at(0)?.value) : (oneDayPrice?.at(0)?.close ?? oneDayPrice?.at(0)?.value) //previousClose; - //colorChange = lastValue < displayLastLogicalRangeValue ? "#CC3636" : "#367E18"; - - colorChange = lastValue < displayLastLogicalRangeValue ? "#FF2F1F" : "#10DB06"; - topColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.2)" : "rgb(16, 219, 6, 0.2)"; - bottomColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.001)" : "rgb(16, 219, 6, 0.001)"; + +async function initializePrice() { + + output = null; + if (intervalId) { + clearInterval(intervalId); + } + intervalId = setInterval(checkChart, 0); + try { + + output = [...data?.getOneDayPrice] ?? []; + oneDayPrice = output?.map(item => ({ time: Date.parse(item?.time), open: item?.open !== null ? item?.open : NaN, high: item?.high !== null ? item?.high : NaN, low: item?.low !== null ? item?.low : NaN, close: item?.close !== null ? item?.close : NaN})); + + displayData = oneDayPrice?.length === 0 && sixMonthPrice?.length !== 0 ? '6M' : '1D'; + //lastValue = oneDayPrice[oneDayPrice?.length - 1]?.value; + if (displayData === '1D') + { + const length = oneDayPrice?.length; + for (let i = length - 1; i >= 0; i--) { + if (!isNaN(oneDayPrice[i]?.close)) { + lastValue = oneDayPrice[i]?.close; + break; + } + } + } + else if (displayData === '6M') { + lastValue = sixMonthPrice?.slice(-1)?.at(0)?.close + } - }; - - + + displayLastLogicalRangeValue = oneDayPrice?.length === 0 && sixMonthPrice?.length !== 0 ? sixMonthPrice?.at(0)?.close : oneDayPrice?.at(0)?.close //previousClose; + + //colorChange = lastValue < displayLastLogicalRangeValue ? "#CC3636" : "#367E18"; + + colorChange = lastValue < displayLastLogicalRangeValue ? "#FF2F1F" : "#10DB06"; + topColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.2)" : "rgb(16, 219, 6, 0.2)"; + bottomColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.001)" : "rgb(16, 219, 6, 0.001)"; + } catch(e) { + console.log(e) + } +}; @@ -678,13 +694,11 @@ if ($etfTicker && typeof window !== 'undefined') // add a check to see if running on client-side { - isLoaded = false; oneDayPrice = []; oneWeekPrice = []; oneMonthPrice = []; oneYearPrice = []; threeYearPrice = []; - pastPriceList = []; geographicList = []; sectorList = []; @@ -714,51 +728,28 @@ //stockDeck = data?.getStockDeckData; - const asyncFunctions = [ - getHistoricalPrice(), - getOneDayPrice(), - getPrePostQuote(), - ]; - - Promise.all(asyncFunctions) - .then((results) => { + + const asyncFunctions = [ + getPrePostQuote(), + ]; + + - isLoaded = true; - }) - .catch((error) => { - console.error('An error occurred:', error); - }); - - - + Promise.all(asyncFunctions) + .then((results) => { + initializePrice() + }) + .catch((error) => { + console.error('An error occurred:', error); + }); + + } } - $: { - if($etfTicker && displayChartType && output !== null && pastPriceList?.length !== 0 && typeof window !== 'undefined') - { - if(displayChartType === 'line') { - oneDayPrice = output?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - oneDayPrice = oneDayPrice?.map(item => ({ time: item?.time, value: item?.value !== null ? item?.value : NaN })); - oneWeekPrice = pastPriceList['1W']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - oneMonthPrice = pastPriceList['1M']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - sixMonthPrice = pastPriceList['6M']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - oneYearPrice = pastPriceList['1Y']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - threeYearPrice = pastPriceList['MAX']?.map(({ time, close }) => ({ time: Date.parse(time), value: close })); - - } - else if (displayChartType === 'candlestick') { - oneDayPrice = output?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneDayPrice = oneDayPrice?.map(item => ({ time: item?.time, open: item?.open !== null ? item?.open : NaN, high: item?.high !== null ? item?.high : NaN, low: item?.low !== null ? item?.low : NaN, close: item?.close !== null ? item?.close : NaN})); - oneWeekPrice = pastPriceList['1W']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneMonthPrice = pastPriceList['1M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - sixMonthPrice = pastPriceList['6M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneYearPrice = pastPriceList['1Y']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - threeYearPrice = pastPriceList['MAX']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - } - } - } - + + + $: { if(form) { @@ -939,7 +930,7 @@ - {#if output !== null && pastPriceList?.length !== 0} + {#if output !== null}
{#if displayData === '1D' && oneDayPrice?.length === 0}

@@ -972,7 +963,7 @@ {#if displayData === '1D'} {#if displayChartType === 'line'} ({ time, value: close }))} lineWidth={1.5} priceScaleId="left" lineColor={colorChange} @@ -984,7 +975,7 @@ lastPriceAnimation={1} > @@ -997,7 +988,7 @@ priceLineVisible= {false} > @@ -1006,7 +997,7 @@ {:else if displayData === '1W'} {#if displayChartType === 'line'} ({ time, value: close }))} lineWidth={1.5} priceScaleId="left" lineColor={colorChange} @@ -1018,7 +1009,7 @@ lastPriceAnimation={1} > @@ -1041,7 +1032,7 @@ {:else if displayData === '1M'} {#if displayChartType === 'line'} ({ time, value: close }))} lineWidth={1.5} priceScaleId="left" lineColor={colorChange} @@ -1053,7 +1044,7 @@ lastPriceAnimation={1} > @@ -1077,7 +1068,7 @@ {:else if displayData === '6M'} {#if displayChartType === 'line'} ({ time, value: close }))} lineWidth={1.5} priceScaleId="left" lineColor={colorChange} @@ -1089,7 +1080,7 @@ lastPriceAnimation={1} > @@ -1114,7 +1105,7 @@ {:else if displayData === '1Y'} {#if displayChartType === 'line'} ({ time, value: close }))} lineWidth={1.5} priceScaleId="left" lineColor={colorChange} @@ -1126,7 +1117,7 @@ lastPriceAnimation={1} > @@ -1151,7 +1142,7 @@ {:else if displayData === 'MAX'} {#if displayChartType === 'line'} ({ time, value: close }))} lineWidth={1.5} priceScaleId="left" lineColor={colorChange} @@ -1163,7 +1154,7 @@ lastPriceAnimation={1} > @@ -1185,7 +1176,7 @@ {/if} - + {/if} diff --git a/src/routes/stocks/[tickerID]/+layout.server.ts b/src/routes/stocks/[tickerID]/+layout.server.ts index 64498f2c..a7e82eaa 100644 --- a/src/routes/stocks/[tickerID]/+layout.server.ts +++ b/src/routes/stocks/[tickerID]/+layout.server.ts @@ -147,7 +147,6 @@ export const load = async ({ params, locals, cookies, setHeaders}) => { fetchData(apiURL,'/wiim',params.tickerID), fetchData(apiURL,'/top-etf-ticker-holder',params.tickerID), fetchData(apiURL,'/value-at-risk',params.tickerID), - fetchData(apiURL,'/historical-price',params.tickerID), fetchData(apiURL,'/one-day-price',params.tickerID), fetchWatchlist(fastifyURL, locals?.user?.id), fetchPortfolio(fastifyURL, locals?.user?.id), @@ -167,7 +166,6 @@ export const load = async ({ params, locals, cookies, setHeaders}) => { getWhyPriceMoved, getTopETFHolder, getVaR, - getHistoricalPrice, getOneDayPrice, getUserWatchlist, getUserPortfolio, @@ -193,7 +191,6 @@ export const load = async ({ params, locals, cookies, setHeaders}) => { getWhyPriceMoved, getTopETFHolder, getVaR, - getHistoricalPrice, getOneDayPrice, getUserWatchlist, getUserPortfolio, diff --git a/src/routes/stocks/[tickerID]/+page.svelte b/src/routes/stocks/[tickerID]/+page.svelte index ac424d29..14a0dd97 100644 --- a/src/routes/stocks/[tickerID]/+page.svelte +++ b/src/routes/stocks/[tickerID]/+page.svelte @@ -3,7 +3,7 @@ import {AreaSeries, Chart, PriceLine, CandlestickSeries} from 'svelte-lightweight-charts'; import { TrackingModeExitMode } from 'lightweight-charts'; - import {screenWidth, displayCompanyName, numberOfUnreadNotification, globalForm, shareholderComponent, trendAnalysisComponent, revenueSegmentationComponent, priceAnalysisComponent, fundamentalAnalysisComponent, userRegion, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, clientSideCache, stockTicker, isOpen, isBeforeMarketOpen, isWeekend} from '$lib/store'; + import {getCache, setCache, screenWidth, displayCompanyName, numberOfUnreadNotification, globalForm, shareholderComponent, trendAnalysisComponent, revenueSegmentationComponent, priceAnalysisComponent, fundamentalAnalysisComponent, userRegion, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, clientSideCache, stockTicker, isOpen, isBeforeMarketOpen, isWeekend} from '$lib/store'; import { onDestroy, onMount } from 'svelte'; import StockKeyInformation from '$lib/components/StockKeyInformation.svelte'; import BullBearSay from '$lib/components/BullBearSay.svelte'; @@ -25,14 +25,11 @@ export let data; export let form; - let isLoaded = false; let displayChartType = 'line'; - let pricePrediction = data?.getPricePrediction ?? []; let stockDeck = data?.getStockDeck ?? []; let fairPrice = data?.getFairPrice ?? []; let correlationList = data?.getCorrelation?.correlation ?? []; - let modelStats = data?.getTradingSignals ?? {}; let prePostData = {}; let similarstock = []; let topETFHolder = []; @@ -176,122 +173,125 @@ $: { - let displayData; - let colorChange; - let topColorChange; - let bottomColorChange; - - let lastValue; - async function changeData(state) { - - switch (state) { - case '1D': - displayData = '1D'; - if(oneDayPrice?.length !== 0) - { - displayLastLogicalRangeValue = oneDayPrice?.at(0)?.close; //previousClose - const length = oneDayPrice?.length; - for (let i = length - 1; i >= 0; i--) { - if (!isNaN(oneDayPrice[i]?.close)) { - lastValue = oneDayPrice[i]?.close; - break; - } +let displayData; +let colorChange; +let topColorChange; +let bottomColorChange; + +let lastValue; +async function changeData(state) { + + switch (state) { + case '1D': + displayData = '1D'; + if(oneDayPrice?.length !== 0) + { + displayLastLogicalRangeValue = oneDayPrice?.at(0)?.close; //previousClose + const length = oneDayPrice?.length; + for (let i = length - 1; i >= 0; i--) { + if (!isNaN(oneDayPrice[i]?.close)) { + lastValue = oneDayPrice[i]?.close; + break; } - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - - - break; - case '1W': - displayData = '1W'; - if(oneWeekPrice?.length !== 0) - { - displayLastLogicalRangeValue = oneWeekPrice?.at(0)?.close; - lastValue = oneWeekPrice?.slice(-1)?.at(0)?.close; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - - - break; - case '1M': - displayData = '1M'; - if(oneMonthPrice?.length !== 0) - { - displayLastLogicalRangeValue = oneMonthPrice?.at(0)?.close; - lastValue = oneMonthPrice.slice(-1)?.at(0)?.close; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - break; - - case '6M': - displayData = '6M'; - if(sixMonthPrice?.length !== 0) - { - displayLastLogicalRangeValue = sixMonthPrice?.at(0)?.close; - lastValue = sixMonthPrice?.slice(-1)?.at(0)?.close; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - break; - case '1Y': - displayData = '1Y'; - if(oneYearPrice?.length !== 0) - { - displayLastLogicalRangeValue = oneYearPrice?.at(0)?.close; - lastValue = oneYearPrice.slice(-1)?.at(0)?.close; - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - } - - break; - case 'MAX': - displayData = 'MAX'; - if(threeYearPrice?.length !== 0) - { - displayLastLogicalRangeValue = threeYearPrice?.at(0)?.close; - lastValue = threeYearPrice.slice(-1)?.at(0)?.close; - - } - else { - displayLastLogicalRangeValue = null; - lastValue = null; - - } - - break; - default: - return; - } - colorChange = lastValue < displayLastLogicalRangeValue ? "#FF2F1F" : "#10DB06"; - topColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.2)" : "rgb(16, 219, 6, 0.2)"; - bottomColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.001)" : "rgb(16, 219, 6, 0.001)"; - - fitContentChart(); - - - //trackButtonClick('Time Period: '+ state) + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + break; + case '1W': + displayData = '1W'; + await historicalPrice('one-week') + if(oneWeekPrice?.length !== 0) + { + displayLastLogicalRangeValue = oneWeekPrice?.at(0)?.close; + lastValue = oneWeekPrice?.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + + + break; + case '1M': + displayData = '1M'; + await historicalPrice('one-month') + if(oneMonthPrice?.length !== 0) + { + displayLastLogicalRangeValue = oneMonthPrice?.at(0)?.close; + lastValue = oneMonthPrice.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + break; + + case '6M': + displayData = '6M'; + await historicalPrice('six-months') + if(sixMonthPrice?.length !== 0) + { + displayLastLogicalRangeValue = sixMonthPrice?.at(0)?.close; + lastValue = sixMonthPrice?.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + break; + case '1Y': + displayData = '1Y'; + await historicalPrice('one-year') + if(oneYearPrice?.length !== 0) + { + displayLastLogicalRangeValue = oneYearPrice?.at(0)?.close; + lastValue = oneYearPrice.slice(-1)?.at(0)?.close; + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + } + + break; + case 'MAX': + displayData = 'MAX'; + await historicalPrice('max') + if(threeYearPrice?.length !== 0) + { + displayLastLogicalRangeValue = threeYearPrice?.at(0)?.close; + lastValue = threeYearPrice.slice(-1)?.at(0)?.close; + + } + else { + displayLastLogicalRangeValue = null; + lastValue = null; + + } + + break; + default: + return; } + colorChange = lastValue < displayLastLogicalRangeValue ? "#FF2F1F" : "#10DB06"; + topColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.2)" : "rgb(16, 219, 6, 0.2)"; + bottomColorChange = lastValue < displayLastLogicalRangeValue ? "rgb(255, 47, 31, 0.001)" : "rgb(16, 219, 6, 0.001)"; + + fitContentChart(); + + + //trackButtonClick('Time Period: '+ state) + } @@ -310,10 +310,88 @@ $: { let oneYearPrice = []; let threeYearPrice = []; - let pastPriceList = []; +async function historicalPrice(timePeriod:string) { + + const cachedData = getCache($stockTicker, 'historicalPrice'+timePeriod); + if (cachedData) { + switch (timePeriod) { + case 'one-week': + oneWeekPrice = cachedData + break; + case 'one-month': + oneMonthPrice = cachedData + break; + case 'six-months': + sixMonthPrice = cachedData + break; + case 'one-year': + oneYearPrice = cachedData + break; + case 'max': + threeYearPrice = cachedData + break; + default: + console.log(`Unsupported time period: ${timePeriod}`); + } + } else { + output = null; + + const postData = { + ticker: $stockTicker, + timePeriod: timePeriod, + }; + + const response = await fetch(apiURL+'/historical-price', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(postData) + }); + + output = await response?.json() ?? []; + + const mapData = (data) => data?.map(({ time, open, high, low, close }) => ({ + time: Date.parse(time), + open, + high, + low, + close + })); + + const mappedData = mapData(output); + try { + switch (timePeriod) { + case 'one-week': + oneWeekPrice = mappedData + break; + case 'one-month': + oneMonthPrice = mappedData + break; + case 'six-months': + sixMonthPrice = mappedData + break; + case 'one-year': + oneYearPrice = mappedData + break; + case 'max': + threeYearPrice = mappedData + break; + default: + console.log(`Unsupported time period: ${timePeriod}`); + } + setCache($stockTicker, mappedData, 'historicalPrice'+timePeriod); + + } catch (e) { + console.log(e); + } + + } +} + async function initializePrice() { @@ -325,17 +403,10 @@ $: { try { output = [...data?.getOneDayPrice] ?? []; - oneDayPrice = data?.getOneDayPrice; - pastPriceList = data?.getHistoricalPrice; oneDayPrice = output?.map(item => ({ time: Date.parse(item?.time), open: item?.open !== null ? item?.open : NaN, high: item?.high !== null ? item?.high : NaN, low: item?.low !== null ? item?.low : NaN, close: item?.close !== null ? item?.close : NaN})); - oneWeekPrice = pastPriceList['1W']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneMonthPrice = pastPriceList['1M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - sixMonthPrice = pastPriceList['6M']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - oneYearPrice = pastPriceList['1Y']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - threeYearPrice = pastPriceList['MAX']?.map(({ time, open,high,low,close }) => ({ time: Date.parse(time), open,high,low,close })); - + displayData = oneDayPrice?.length === 0 && sixMonthPrice?.length !== 0 ? '6M' : '1D'; //lastValue = oneDayPrice[oneDayPrice?.length - 1]?.value; if (displayData === '1D') @@ -609,13 +680,11 @@ function changeChartType() { if ($stockTicker && typeof window !== 'undefined') // add a check to see if running on client-side { - isLoaded = false; oneDayPrice = []; oneWeekPrice = []; oneMonthPrice = []; oneYearPrice = []; threeYearPrice = []; - pastPriceList = []; optionsDict = {}; prePostData = {}; marketMoods = {}; @@ -626,8 +695,6 @@ function changeChartType() { fairPrice = data?.getFairPrice; - pricePrediction = data?.getPricePrediction; - modelStats = data?.getTradingSignals; stockDeck = data?.getStockDeck; correlationList = data?.getCorrelation?.correlation; previousClose = data?.getStockQuote?.previousClose; @@ -652,7 +719,6 @@ function changeChartType() { Promise.all(asyncFunctions) .then((results) => { initializePrice() - isLoaded = true; }) .catch((error) => { console.error('An error occurred:', error); @@ -847,7 +913,7 @@ function changeChartType() { - {#if output !== null && pastPriceList?.length !== 0} + {#if output !== null}
{#if displayData === '1D' && oneDayPrice?.length === 0}

@@ -1293,36 +1359,6 @@ function changeChartType() { - - - - - - - - - - - -