friendlier variable names; use sliders for input
This commit is contained in:
@@ -16,6 +16,7 @@ import {
|
||||
Paper,
|
||||
Popper,
|
||||
ClickAwayListener,
|
||||
Stack,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
availableUnderlyings,
|
||||
@@ -38,9 +39,9 @@ import {
|
||||
refreshStockPriceChartData,
|
||||
} from "./HistoricalCalendarPrices/actions.js";
|
||||
import { EditableUnderlying } from "./HistoricalCalendarPrices/EditableUnderlying.js";
|
||||
import { EditableDaysToFrontExpiration } from "./HistoricalCalendarPrices/EditableDaysToFrontExpiration.js";
|
||||
import { EditableExitToFrontExpiration } from "./HistoricalCalendarPrices/EditableExitToFrontExpiration.js";
|
||||
import { EditableDaysBetweenFrontAndBackExpiration } from "./HistoricalCalendarPrices/EditableDaysBetweenFrontAndBackExpiration.js";
|
||||
import { EditableOpenDTE } from "./HistoricalCalendarPrices/EditableOpenDTE.js";
|
||||
import { EditableExitDTE } from "./HistoricalCalendarPrices/EditableExitDTE.js";
|
||||
import { EditableSpan } from "./HistoricalCalendarPrices/EditableSpan.js";
|
||||
import { EditableLookbackPeriodStart } from "./HistoricalCalendarPrices/EditableLookbackPeriodStart.js";
|
||||
import { EditableLookbackPeriodEnd } from "./HistoricalCalendarPrices/EditableLookbackPeriodEnd.js";
|
||||
|
||||
@@ -64,16 +65,16 @@ export function HistoricalCalendarPrices() {
|
||||
return (
|
||||
<Container maxWidth="lg">
|
||||
<Grid2 container spacing={4} columns={12}>
|
||||
<Grid2 size={{ xs: 12 }}>
|
||||
{/* <Grid2 size={{ xs: 12 }}>
|
||||
|
||||
<Typography variant="h4" gutterBottom>
|
||||
<EditableUnderlying /> :
|
||||
<EditableDaysBetweenFrontAndBackExpiration />
|
||||
<EditableSpan />
|
||||
-Day Calendar @ <EditableStrike />
|
||||
%-from-the-money
|
||||
</Typography>
|
||||
<Typography variant="h5" gutterBottom sx={{ pl: 1 }}>
|
||||
Opening at <EditableDaysToFrontExpiration /> DTE, Closing at{" "}
|
||||
<EditableExitToFrontExpiration />
|
||||
Opening at <EditableOpenDTE /> DTE, Closing at <EditableExitDTE />
|
||||
DTE
|
||||
</Typography>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
@@ -93,72 +94,55 @@ export function HistoricalCalendarPrices() {
|
||||
</Paper>
|
||||
</Popper>
|
||||
</ClickAwayListener>
|
||||
</Grid2>
|
||||
</Grid2> */}
|
||||
|
||||
<Grid2 size={{ xs: 12 }}>
|
||||
<Paper elevation={3} sx={{ p: 3, minHeight: "28em", height: "100%" }}>
|
||||
{underlying.value !== null &&
|
||||
stockPriceChartData.value.length > 0 ? (
|
||||
<Scatter
|
||||
data={{
|
||||
datasets: [
|
||||
{
|
||||
label: "Stock Open Price",
|
||||
data: stockPriceChartData.value,
|
||||
},
|
||||
],
|
||||
}}
|
||||
options={{
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: "Time",
|
||||
},
|
||||
ticks: {
|
||||
callback: (value, index, ticks) =>
|
||||
new Date((value as number) * 1000)
|
||||
.toISOString()
|
||||
.substring(0, 10),
|
||||
},
|
||||
min: new Date(lookbackPeriodStart.value).getTime() / 1000,
|
||||
max: new Date(lookbackPeriodEnd.value).getTime() / 1000,
|
||||
},
|
||||
y: {
|
||||
beginAtZero: false,
|
||||
ticks: {
|
||||
callback: (value, index, ticks) =>
|
||||
`$${value.toString()}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
radius: 1,
|
||||
borderWidth: 0,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: "Stock Price",
|
||||
},
|
||||
},
|
||||
animation: false,
|
||||
maintainAspectRatio: false,
|
||||
events: [],
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Typography>Loading Chart...</Typography>
|
||||
)}
|
||||
</Paper>
|
||||
<Stack direction="row" spacing={2}>
|
||||
<Typography gutterBottom minWidth={"8em"}>
|
||||
Underlying
|
||||
</Typography>
|
||||
<EditableUnderlying />
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={2}>
|
||||
<Typography gutterBottom minWidth={"8em"}>
|
||||
Open DTE
|
||||
</Typography>
|
||||
<EditableOpenDTE />
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={2}>
|
||||
<Typography gutterBottom minWidth={"8em"}>
|
||||
Exit DTE
|
||||
</Typography>
|
||||
<EditableExitDTE />
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={2}>
|
||||
<Typography gutterBottom minWidth={"8em"}>
|
||||
Span
|
||||
</Typography>
|
||||
<EditableSpan />
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={2}>
|
||||
<Typography gutterBottom minWidth={"8em"}>
|
||||
Lookback Period
|
||||
</Typography>
|
||||
<EditableLookbackPeriodStart />-
|
||||
<EditableLookbackPeriodEnd />
|
||||
</Stack>
|
||||
<ClickAwayListener
|
||||
onClickAway={() => {
|
||||
isPopperOpen.value = false;
|
||||
// refreshSimilarCalendarPriceChartData();
|
||||
console.log("clicked away");
|
||||
}}
|
||||
>
|
||||
<Popper open={isPopperOpen.value} anchorEl={popperAnchorEl.value}>
|
||||
<Paper elevation={3} sx={{ p: 3 }}>
|
||||
{popperContent.value}
|
||||
</Paper>
|
||||
</Popper>
|
||||
</ClickAwayListener>
|
||||
</Grid2>
|
||||
|
||||
<Grid2 size={{ xs: 12, md: 6 }}>
|
||||
<Paper elevation={3} sx={{ p: 3, minHeight: "28em" }}>
|
||||
{underlying.value !== null &&
|
||||
@@ -294,6 +278,71 @@ export function HistoricalCalendarPrices() {
|
||||
)}
|
||||
</Paper>
|
||||
</Grid2>
|
||||
<Grid2 size={{ xs: 12 }}>
|
||||
<Paper elevation={3} sx={{ p: 3, minHeight: "28em", height: "100%" }}>
|
||||
{underlying.value !== null &&
|
||||
stockPriceChartData.value.length > 0 ? (
|
||||
<Scatter
|
||||
data={{
|
||||
datasets: [
|
||||
{
|
||||
label: "Stock Open Price",
|
||||
data: stockPriceChartData.value,
|
||||
},
|
||||
],
|
||||
}}
|
||||
options={{
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: "Time",
|
||||
},
|
||||
ticks: {
|
||||
callback: (value, index, ticks) =>
|
||||
new Date((value as number) * 1000)
|
||||
.toISOString()
|
||||
.substring(0, 10),
|
||||
},
|
||||
min: new Date(lookbackPeriodStart.value).getTime() / 1000,
|
||||
max: new Date(lookbackPeriodEnd.value).getTime() / 1000,
|
||||
},
|
||||
y: {
|
||||
beginAtZero: false,
|
||||
ticks: {
|
||||
callback: (value, index, ticks) =>
|
||||
`$${value.toString()}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
radius: 1,
|
||||
borderWidth: 0,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: "Stock Price",
|
||||
},
|
||||
},
|
||||
animation: false,
|
||||
maintainAspectRatio: false,
|
||||
events: [],
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Typography>Loading Chart...</Typography>
|
||||
)}
|
||||
</Paper>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Container>
|
||||
);
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
import TextField from "@mui/material/TextField";
|
||||
import {
|
||||
refreshcalendarExitPriceChartData,
|
||||
refreshSimilarCalendarPriceChartData,
|
||||
} from "./actions";
|
||||
import { daysBetweenFrontAndBackExpiration } from "./state";
|
||||
import { EditableValue } from "./EditableValue";
|
||||
|
||||
const handleDaysBetweenFrontAndBackExpirationChange = (e) => {
|
||||
if (
|
||||
daysBetweenFrontAndBackExpiration.value !== Number.parseInt(e.target.value)
|
||||
) {
|
||||
daysBetweenFrontAndBackExpiration.value = Number.parseInt(e.target.value);
|
||||
refreshSimilarCalendarPriceChartData();
|
||||
refreshcalendarExitPriceChartData();
|
||||
}
|
||||
};
|
||||
|
||||
function DaysBetweenFrontAndBackExpirationChooser() {
|
||||
return (
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Front-to-Back-Month Days to Expiration Difference"
|
||||
type="number"
|
||||
value={daysBetweenFrontAndBackExpiration.value}
|
||||
onChange={handleDaysBetweenFrontAndBackExpirationChange}
|
||||
InputProps={{ endAdornment: "Days Difference" }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function EditableDaysBetweenFrontAndBackExpiration() {
|
||||
return (
|
||||
<EditableValue text={daysBetweenFrontAndBackExpiration.value}>
|
||||
<DaysBetweenFrontAndBackExpirationChooser />
|
||||
</EditableValue>
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { refreshSimilarCalendarPriceChartData } from "./actions";
|
||||
import { EditableValue } from "./EditableValue";
|
||||
import { daysToFrontExpiration } from "./state";
|
||||
|
||||
const handleDaysToFrontExpirationChange = (e) => {
|
||||
if (daysToFrontExpiration.value !== Number.parseInt(e.target.value)) {
|
||||
daysToFrontExpiration.value = Number.parseInt(e.target.value);
|
||||
refreshSimilarCalendarPriceChartData();
|
||||
}
|
||||
};
|
||||
|
||||
function DaysToFrontExpirationChooser() {
|
||||
return (
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Now-to-Front-Month Days to Expiration"
|
||||
type="number"
|
||||
value={daysToFrontExpiration.value}
|
||||
onChange={handleDaysToFrontExpirationChange}
|
||||
InputProps={{ endAdornment: "Days" }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function EditableDaysToFrontExpiration() {
|
||||
return (
|
||||
<EditableValue text={daysToFrontExpiration.value}>
|
||||
<DaysToFrontExpirationChooser />
|
||||
</EditableValue>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { EditableValue } from "./EditableValue";
|
||||
import { exitDTE } from "./state";
|
||||
import { refreshcalendarExitPriceChartData } from "./actions";
|
||||
import Slider from "@mui/material/Slider";
|
||||
|
||||
const handleExitDTEChange = (e) => {
|
||||
if (exitDTE.value !== Number.parseInt(e.target.value)) {
|
||||
exitDTE.value = Number.parseInt(e.target.value);
|
||||
refreshcalendarExitPriceChartData();
|
||||
}
|
||||
};
|
||||
|
||||
export function EditableExitDTE() {
|
||||
return (
|
||||
<Slider
|
||||
value={exitDTE.value}
|
||||
onChange={handleExitDTEChange}
|
||||
min={0}
|
||||
max={5}
|
||||
step={1}
|
||||
valueLabelDisplay="on"
|
||||
/>
|
||||
// <EditableValue text={exitDTE.value}>
|
||||
// <ExitToFrontExpirationChooser />
|
||||
// </EditableValue>
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { EditableValue } from "./EditableValue";
|
||||
import { exitToFrontExpiration } from "./state";
|
||||
import { refreshcalendarExitPriceChartData } from "./actions";
|
||||
|
||||
const handleExitToFrontExpirationChange = (e) => {
|
||||
if (exitToFrontExpiration.value !== Number.parseInt(e.target.value)) {
|
||||
exitToFrontExpiration.value = Number.parseInt(e.target.value);
|
||||
refreshcalendarExitPriceChartData();
|
||||
}
|
||||
};
|
||||
|
||||
function ExitToFrontExpirationChooser() {
|
||||
return (
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Exit-to-Front-Month Days to Expiration"
|
||||
type="number"
|
||||
value={exitToFrontExpiration.value}
|
||||
onChange={handleExitToFrontExpirationChange}
|
||||
InputProps={{ endAdornment: "Days" }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function EditableExitToFrontExpiration() {
|
||||
return (
|
||||
<EditableValue text={exitToFrontExpiration.value}>
|
||||
<ExitToFrontExpirationChooser />
|
||||
</EditableValue>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { refreshSimilarCalendarPriceChartData } from "./actions";
|
||||
import { openDTE } from "./state";
|
||||
import Slider from "@mui/material/Slider";
|
||||
|
||||
const handleOpenDTEChange = (e) => {
|
||||
if (openDTE.value !== Number.parseInt(e.target.value)) {
|
||||
openDTE.value = Number.parseInt(e.target.value);
|
||||
refreshSimilarCalendarPriceChartData();
|
||||
}
|
||||
};
|
||||
|
||||
export function EditableOpenDTE() {
|
||||
return (
|
||||
<Slider
|
||||
value={openDTE.value}
|
||||
onChange={handleOpenDTEChange}
|
||||
min={0}
|
||||
max={5}
|
||||
step={1}
|
||||
valueLabelDisplay="on"
|
||||
/>
|
||||
// <EditableValue text={openDTE.value}>
|
||||
// <DaysToFrontExpirationChooser />
|
||||
// </EditableValue>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import TextField from "@mui/material/TextField";
|
||||
import {
|
||||
refreshcalendarExitPriceChartData,
|
||||
refreshSimilarCalendarPriceChartData,
|
||||
} from "./actions";
|
||||
import { span } from "./state";
|
||||
import { EditableValue } from "./EditableValue";
|
||||
import Slider from "@mui/material/Slider";
|
||||
|
||||
const handleSpanChange = (e) => {
|
||||
if (span.value !== Number.parseInt(e.target.value)) {
|
||||
span.value = Number.parseInt(e.target.value);
|
||||
refreshSimilarCalendarPriceChartData();
|
||||
refreshcalendarExitPriceChartData();
|
||||
}
|
||||
};
|
||||
|
||||
function DaysBetweenFrontAndBackExpirationChooser() {
|
||||
return (
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Front-to-Back-Month Days to Expiration Difference"
|
||||
type="number"
|
||||
value={span.value}
|
||||
onChange={handleSpanChange}
|
||||
InputProps={{ endAdornment: "Days Difference" }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function EditableSpan() {
|
||||
return (
|
||||
<Slider
|
||||
value={span.value}
|
||||
onChange={handleSpanChange}
|
||||
min={3}
|
||||
max={45}
|
||||
step={1}
|
||||
valueLabelDisplay="on"
|
||||
/>
|
||||
// <EditableValue text={span.value}>
|
||||
// <DaysBetweenFrontAndBackExpirationChooser />
|
||||
// </EditableValue>
|
||||
);
|
||||
}
|
||||
@@ -1,24 +1,21 @@
|
||||
import Box from "@mui/material/Box";
|
||||
import { EditableValue } from "./EditableValue";
|
||||
import {
|
||||
strikePercentageFromUnderlyingPrice,
|
||||
strikePercentageFromUnderlyingPriceRadius,
|
||||
} from "./state";
|
||||
import { moniness, moninessRadius } from "./state";
|
||||
import Slider from "@mui/material/Slider";
|
||||
import { refreshSimilarCalendarPriceChartData } from "./actions";
|
||||
|
||||
function StrikePercentageFromUnderlyingPriceChooser() {
|
||||
function MoninessChooser() {
|
||||
return (
|
||||
<Slider
|
||||
fullWidth
|
||||
label="Strike % From Underlying Price"
|
||||
value={strikePercentageFromUnderlyingPrice.value}
|
||||
value={moniness.value}
|
||||
valueLabelDisplay="on"
|
||||
min={0}
|
||||
max={10}
|
||||
step={1}
|
||||
onChange={(e, value) => {
|
||||
strikePercentageFromUnderlyingPrice.value = value as number;
|
||||
moniness.value = value as number;
|
||||
}}
|
||||
onChangeCommitted={(e, value) => {
|
||||
refreshSimilarCalendarPriceChartData();
|
||||
@@ -28,18 +25,18 @@ function StrikePercentageFromUnderlyingPriceChooser() {
|
||||
);
|
||||
}
|
||||
|
||||
function StrikePercentageFromUnderlyingPriceRadiusChooser() {
|
||||
function MoninessRadiusChooser() {
|
||||
return (
|
||||
<Slider
|
||||
fullWidth
|
||||
label="Strike % Radius"
|
||||
value={strikePercentageFromUnderlyingPriceRadius.value}
|
||||
value={moninessRadius.value}
|
||||
valueLabelDisplay="on"
|
||||
min={0}
|
||||
max={10}
|
||||
step={1}
|
||||
onChange={(e, value) => {
|
||||
strikePercentageFromUnderlyingPriceRadius.value = value as number;
|
||||
moninessRadius.value = value as number;
|
||||
}}
|
||||
onChangeCommitted={(e, value) => {
|
||||
refreshSimilarCalendarPriceChartData();
|
||||
@@ -57,13 +54,11 @@ function StrikePercentageFromUnderlyingPriceRadiusChooser() {
|
||||
export function EditableStrike() {
|
||||
return (
|
||||
<EditableValue
|
||||
text={`${strikePercentageFromUnderlyingPrice.value.toFixed(
|
||||
1
|
||||
)}±${strikePercentageFromUnderlyingPriceRadius.value.toFixed(2)}`}
|
||||
text={`${moniness.value.toFixed(1)}±${moninessRadius.value.toFixed(2)}`}
|
||||
>
|
||||
<Box sx={{ minWidth: "20em" }}>
|
||||
<StrikePercentageFromUnderlyingPriceChooser />
|
||||
<StrikePercentageFromUnderlyingPriceRadiusChooser />
|
||||
<MoninessChooser />
|
||||
<MoninessRadiusChooser />
|
||||
</Box>
|
||||
</EditableValue>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { trpc } from "../../trpc";
|
||||
import {
|
||||
calendarExitPriceChartData,
|
||||
daysBetweenFrontAndBackExpiration,
|
||||
daysToFrontExpiration,
|
||||
exitToFrontExpiration,
|
||||
span,
|
||||
openDTE,
|
||||
exitDTE,
|
||||
lookbackPeriodEnd,
|
||||
lookbackPeriodStart,
|
||||
similarCalendarPriceChartData,
|
||||
stockPriceChartData,
|
||||
strikePercentageFromUnderlyingPrice,
|
||||
strikePercentageFromUnderlyingPriceRadius,
|
||||
moniness,
|
||||
moninessRadius,
|
||||
underlying,
|
||||
} from "./state";
|
||||
|
||||
@@ -30,17 +30,12 @@ export const refreshSimilarCalendarPriceChartData = () => {
|
||||
trpc.SimilarCalendarPriceChart.getChartData
|
||||
.query({
|
||||
underlying: underlying.value,
|
||||
daysToFrontExpiration: daysToFrontExpiration.value,
|
||||
daysBetweenFrontAndBackExpiration:
|
||||
daysBetweenFrontAndBackExpiration.value,
|
||||
daysToFrontExpiration: openDTE.value,
|
||||
daysBetweenFrontAndBackExpiration: span.value,
|
||||
strikePercentageFromUnderlyingPriceRangeMin:
|
||||
(strikePercentageFromUnderlyingPrice.value -
|
||||
strikePercentageFromUnderlyingPriceRadius.value) /
|
||||
100,
|
||||
(moniness.value - moninessRadius.value) / 100,
|
||||
strikePercentageFromUnderlyingPriceRangeMax:
|
||||
(strikePercentageFromUnderlyingPrice.value +
|
||||
strikePercentageFromUnderlyingPriceRadius.value) /
|
||||
100,
|
||||
(moniness.value + moninessRadius.value) / 100,
|
||||
lookbackPeriodStart: lookbackPeriodStart.value,
|
||||
lookbackPeriodEnd: lookbackPeriodEnd.value,
|
||||
})
|
||||
@@ -53,9 +48,8 @@ export const refreshcalendarExitPriceChartData = () => {
|
||||
trpc.CalendarExitPriceChart.getChartData
|
||||
.query({
|
||||
underlying: underlying.value,
|
||||
daysToFrontExpiration: exitToFrontExpiration.value,
|
||||
daysBetweenFrontAndBackExpiration:
|
||||
daysBetweenFrontAndBackExpiration.value,
|
||||
daysToFrontExpiration: exitDTE.value,
|
||||
daysBetweenFrontAndBackExpiration: span.value,
|
||||
lookbackPeriodStart: lookbackPeriodStart.value,
|
||||
lookbackPeriodEnd: lookbackPeriodEnd.value,
|
||||
})
|
||||
|
||||
@@ -7,14 +7,14 @@ export const popperContent = signal(null);
|
||||
export const availableUnderlyings = signal([]);
|
||||
export const underlying = signal(null);
|
||||
|
||||
export const daysToFrontExpiration = signal(14);
|
||||
export const openDTE = signal(14);
|
||||
|
||||
export const daysBetweenFrontAndBackExpiration = signal(14);
|
||||
export const span = signal(14);
|
||||
|
||||
export const strikePercentageFromUnderlyingPrice = signal(1);
|
||||
export const strikePercentageFromUnderlyingPriceRadius = signal(1);
|
||||
export const moniness = signal(1);
|
||||
export const moninessRadius = signal(1);
|
||||
|
||||
export const exitToFrontExpiration = signal(2);
|
||||
export const exitDTE = signal(2);
|
||||
|
||||
export const stockPriceChartData = signal([]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user