import { signal, computed } from "@preact/signals"; import { useEffect } from "preact/hooks"; import { trpc } from "../trpc.js"; import { Chart as ChartJS, LinearScale, CategoryScale, PointElement, Tooltip, Title, } from "chart.js"; import { Scatter } from "react-chartjs-2"; import { Container, Grid, Typography, TextField, Select, MenuItem, InputLabel, FormControl, Paper, } from "@mui/material"; ChartJS.register(LinearScale, CategoryScale, PointElement, Tooltip, Title); const availableUnderlyings = signal([]); const chosenUnderlying = signal(null); const chosenDaysToFrontExpiration = signal(14); const chosenDaysBetweenFrontAndBackExpiration = signal(14); const chosenStrikePercentageFromUnderlyingPrice = signal(1.4); const chosenStrikePercentageFromUnderlyingPriceRadius = signal(0.05); const chosenExitToFrontExpiration = signal(2); const historicalStockQuoteChartData = signal([]); const historicalCalendarQuoteChartData = signal([]); const historicalCalendarExitQuoteChartData = signal([]); const chosenLookbackPeriodStart = signal("2022-01-01"); const chosenLookbackPeriodEnd = signal("2024-01-01"); const maxChartPrice = computed(() => Math.max( Math.max.apply( null, historicalCalendarQuoteChartData.value.map((d) => d.y) ), Math.max.apply( null, historicalCalendarExitQuoteChartData.value.map((d) => d.y) ) ) ); const maxN = computed(() => Math.max.apply( null, historicalCalendarExitQuoteChartData.value.map((d) => d.n) ) ); const refreshHistoricalStockQuoteChartData = () => { historicalStockQuoteChartData.value = []; trpc.getHistoricalStockQuoteChartData .query({ underlying: chosenUnderlying.value, lookbackPeriodStart: chosenLookbackPeriodStart.value, lookbackPeriodEnd: chosenLookbackPeriodEnd.value, }) .then((getHistoricalStockQuoteChartDataResponse) => { historicalStockQuoteChartData.value = getHistoricalStockQuoteChartDataResponse; }); }; const refreshHistoricalCalendarQuoteChartData = () => { historicalCalendarQuoteChartData.value = []; trpc.getHistoricalCalendarQuoteChartData .query({ underlying: chosenUnderlying.value, daysToFrontExpiration: chosenDaysToFrontExpiration.value, daysBetweenFrontAndBackExpiration: chosenDaysBetweenFrontAndBackExpiration.value, strikePercentageFromUnderlyingPriceRangeMin: chosenStrikePercentageFromUnderlyingPrice.value - chosenStrikePercentageFromUnderlyingPriceRadius.value, strikePercentageFromUnderlyingPriceRangeMax: chosenStrikePercentageFromUnderlyingPrice.value + chosenStrikePercentageFromUnderlyingPriceRadius.value, lookbackPeriodStart: chosenLookbackPeriodStart.value, lookbackPeriodEnd: chosenLookbackPeriodEnd.value, }) .then((getHistoricalCalendarQuoteChartDataResponse) => { historicalCalendarQuoteChartData.value = getHistoricalCalendarQuoteChartDataResponse; }); }; const refreshHistoricalCalendarExitQuoteChartData = () => { historicalCalendarExitQuoteChartData.value = []; trpc.getHistoricalCalendarExitQuoteChartData .query({ underlying: chosenUnderlying.value, daysToFrontExpiration: chosenExitToFrontExpiration.value, daysBetweenFrontAndBackExpiration: chosenDaysBetweenFrontAndBackExpiration.value, lookbackPeriodStart: chosenLookbackPeriodStart.value, lookbackPeriodEnd: chosenLookbackPeriodEnd.value, }) .then((getHistoricalCalendarExitQuoteChartDataResponse) => { historicalCalendarExitQuoteChartData.value = getHistoricalCalendarExitQuoteChartDataResponse; }); }; const handleInit = () => { trpc.getAvailableUnderlyings.query().then((availableUnderlyingsResponse) => { availableUnderlyings.value = availableUnderlyingsResponse; chosenUnderlying.value = availableUnderlyingsResponse[0]; refreshHistoricalStockQuoteChartData(); refreshHistoricalCalendarQuoteChartData(); refreshHistoricalCalendarExitQuoteChartData(); }); }; const handleUnderlyingChange = (e) => { if (chosenUnderlying.value !== e.target.value) { chosenUnderlying.value = e.target.value; refreshHistoricalStockQuoteChartData(); refreshHistoricalCalendarQuoteChartData(); refreshHistoricalCalendarExitQuoteChartData(); } }; const handleDaysToFrontExpirationChange = (e) => { if (chosenDaysToFrontExpiration.value !== parseInt(e.target.value)) { chosenDaysToFrontExpiration.value = parseInt(e.target.value); refreshHistoricalCalendarQuoteChartData(); } }; const handleDaysBetweenFrontAndBackExpirationChange = (e) => { if ( chosenDaysBetweenFrontAndBackExpiration.value !== parseInt(e.target.value) ) { chosenDaysBetweenFrontAndBackExpiration.value = parseInt(e.target.value); refreshHistoricalCalendarQuoteChartData(); refreshHistoricalCalendarExitQuoteChartData(); } }; const handleStrikePercentageFromUnderlyingPriceChange = (e) => { if ( chosenStrikePercentageFromUnderlyingPrice.value !== parseFloat(e.target.value) ) { chosenStrikePercentageFromUnderlyingPrice.value = parseFloat( e.target.value ); refreshHistoricalCalendarQuoteChartData(); } }; const handleStrikePercentageFromUnderlyingPriceRadiusChange = (e) => { if ( chosenStrikePercentageFromUnderlyingPriceRadius.value !== parseFloat(e.target.value) ) { chosenStrikePercentageFromUnderlyingPriceRadius.value = parseFloat( e.target.value ); refreshHistoricalCalendarQuoteChartData(); } }; const handleExitToFrontExpirationChange = (e) => { if (chosenExitToFrontExpiration.value !== parseInt(e.target.value)) { chosenExitToFrontExpiration.value = parseInt(e.target.value); refreshHistoricalCalendarExitQuoteChartData(); } }; const handleLookbackPeriodStartChange = (e) => { if (chosenLookbackPeriodStart.value !== e.target.value) { chosenLookbackPeriodStart.value = e.target.value; refreshHistoricalStockQuoteChartData(); refreshHistoricalCalendarQuoteChartData(); refreshHistoricalCalendarExitQuoteChartData(); } }; const handleLookbackPeriodEndChange = (e) => { if (chosenLookbackPeriodEnd.value !== e.target.value) { chosenLookbackPeriodEnd.value = e.target.value; refreshHistoricalStockQuoteChartData(); refreshHistoricalCalendarQuoteChartData(); refreshHistoricalCalendarExitQuoteChartData(); } }; export function HistoricalCalendarPrices() { useEffect(handleInit, []); return ( Historical Calendar Prices Available Underlyings handleLookbackPeriodStartChange({ target: { value: e.target.value } })} InputLabelProps={{ shrink: true }} /> handleLookbackPeriodEndChange({ target: { value: e.target.value } })} InputLabelProps={{ shrink: true }} /> {chosenUnderlying.value !== null && historicalStockQuoteChartData.value.length > 0 ? ( ) : ( Loading Chart... )} {chosenUnderlying.value !== null && historicalCalendarQuoteChartData.value.length > 0 ? ( ) : ( Loading Chart... )} {chosenUnderlying.value !== null && historicalCalendarQuoteChartData.value.length > 0 ? ( ) : ( Loading Chart... )} ); }