init
This commit is contained in:
@@ -0,0 +1,321 @@
|
||||
import { signal } from "@preact/signals";
|
||||
import { useCallback, 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 './style.css';
|
||||
|
||||
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([]);
|
||||
|
||||
|
||||
export function HistoricalCalendarPrices(){
|
||||
const refreshHistoricalStockQuoteChartData = useCallback(()=>{
|
||||
trpc.getHistoricalStockQuoteChartData
|
||||
.query({
|
||||
underlying:chosenUnderlying.value,
|
||||
})
|
||||
.then((getHistoricalStockQuoteChartDataResponse)=>{
|
||||
historicalStockQuoteChartData.value = getHistoricalStockQuoteChartDataResponse;
|
||||
})
|
||||
},[]);
|
||||
const refreshHistoricalCalendarQuoteChartData = useCallback(()=>{
|
||||
trpc.getHistoricalCalendarQuoteChartData
|
||||
.query({
|
||||
underlying:chosenUnderlying.value,
|
||||
daysToFrontExpiration:chosenDaysToFrontExpiration.value,
|
||||
daysBetweenFrontAndBackExpiration:chosenDaysBetweenFrontAndBackExpiration.value,
|
||||
strikePercentageFromUnderlyingPriceRangeMin:chosenStrikePercentageFromUnderlyingPrice.value - chosenStrikePercentageFromUnderlyingPriceRadius.value,
|
||||
strikePercentageFromUnderlyingPriceRangeMax:chosenStrikePercentageFromUnderlyingPrice.value + chosenStrikePercentageFromUnderlyingPriceRadius.value,
|
||||
})
|
||||
.then((getHistoricalCalendarQuoteChartDataResponse)=>{
|
||||
historicalCalendarQuoteChartData.value = getHistoricalCalendarQuoteChartDataResponse;
|
||||
})
|
||||
},[]);
|
||||
const refreshHistoricalCalendarExitQuoteChartData = useCallback(()=>{
|
||||
trpc.getHistoricalCalendarExitQuoteChartData
|
||||
.query({
|
||||
underlying:chosenUnderlying.value,
|
||||
daysToFrontExpiration:chosenExitToFrontExpiration.value,
|
||||
daysBetweenFrontAndBackExpiration:chosenDaysBetweenFrontAndBackExpiration.value,
|
||||
})
|
||||
.then((getHistoricalCalendarExitQuoteChartDataResponse)=>{
|
||||
historicalCalendarExitQuoteChartData.value = getHistoricalCalendarExitQuoteChartDataResponse;
|
||||
})
|
||||
},[]);
|
||||
const handleInit = useCallback(()=>{
|
||||
trpc.getAvailableUnderlyings
|
||||
.query()
|
||||
.then((availableUnderlyingsResponse)=>{
|
||||
availableUnderlyings.value = availableUnderlyingsResponse;
|
||||
chosenUnderlying.value = availableUnderlyingsResponse[0];
|
||||
refreshHistoricalStockQuoteChartData();
|
||||
refreshHistoricalCalendarQuoteChartData();
|
||||
refreshHistoricalCalendarExitQuoteChartData();
|
||||
});
|
||||
},[]);
|
||||
const handleUnderlyingChange = useCallback((e)=>{
|
||||
chosenUnderlying.value = e.target.value;
|
||||
refreshHistoricalStockQuoteChartData();
|
||||
refreshHistoricalCalendarQuoteChartData();
|
||||
refreshHistoricalCalendarExitQuoteChartData();
|
||||
},[]);
|
||||
const handleDaysToFrontExpirationChange = useCallback((e)=>{
|
||||
chosenDaysToFrontExpiration.value = parseInt(e.target.value);
|
||||
refreshHistoricalCalendarQuoteChartData();
|
||||
},[]);
|
||||
const handleDaysBetweenFrontAndBackExpirationChange = useCallback((e)=>{
|
||||
chosenDaysBetweenFrontAndBackExpiration.value = parseInt(e.target.value);
|
||||
refreshHistoricalCalendarQuoteChartData();
|
||||
refreshHistoricalCalendarExitQuoteChartData();
|
||||
},[]);
|
||||
const handleStrikePercentageFromUnderlyingPriceChange = useCallback((e)=>{
|
||||
chosenStrikePercentageFromUnderlyingPrice.value = parseFloat(e.target.value);
|
||||
refreshHistoricalCalendarQuoteChartData();
|
||||
},[]);
|
||||
const handleStrikePercentageFromUnderlyingPriceRadiusChange = useCallback((e)=>{
|
||||
chosenStrikePercentageFromUnderlyingPriceRadius.value = parseFloat(e.target.value);
|
||||
refreshHistoricalCalendarQuoteChartData();
|
||||
},[]);
|
||||
const handleExitToFrontExpirationChange = useCallback((e)=>{
|
||||
chosenExitToFrontExpiration.value = parseInt(e.target.value);
|
||||
refreshHistoricalCalendarExitQuoteChartData();
|
||||
},[]);
|
||||
|
||||
useEffect(handleInit, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<label>Available Underlyings</label>
|
||||
{
|
||||
availableUnderlyings.value.length === 0
|
||||
? "Loading..."
|
||||
: <select onChange={handleUnderlyingChange}>
|
||||
{availableUnderlyings.value.map((availableUnderlying)=>(
|
||||
<option value={availableUnderlying}>{availableUnderlying}</option>
|
||||
))}
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<label>Now-to-Front-Month "Days to Expiration"</label>
|
||||
<input type="text" onChange={handleDaysToFrontExpirationChange} value={chosenDaysToFrontExpiration.value} />
|
||||
Days
|
||||
</div>
|
||||
<div>
|
||||
<label>Front-to-Back-Month "Days to Expiration" Difference</label>
|
||||
<input type="text" onChange={handleDaysBetweenFrontAndBackExpirationChange} value={chosenDaysBetweenFrontAndBackExpiration.value} />
|
||||
Days Difference
|
||||
</div>
|
||||
<div>
|
||||
<label>"Strike Percentage From Underlying Price" Range</label>
|
||||
<input type="text" onChange={handleStrikePercentageFromUnderlyingPriceChange} value={chosenStrikePercentageFromUnderlyingPrice.value} />
|
||||
%
|
||||
+/-
|
||||
<input type="text" onChange={handleStrikePercentageFromUnderlyingPriceRadiusChange} value={chosenStrikePercentageFromUnderlyingPriceRadius.value} />
|
||||
% from ATM
|
||||
</div>
|
||||
<div>
|
||||
<label>Exit-to-Front-Month "Days to Expiration"</label>
|
||||
<input type="text" onChange={handleExitToFrontExpirationChange} value={chosenExitToFrontExpiration.value} />
|
||||
Days
|
||||
</div>
|
||||
<div className="chart-container">
|
||||
{chosenUnderlying.value!==null && historicalStockQuoteChartData.value.length>0
|
||||
? <div className="chart">
|
||||
<Scatter
|
||||
data={{
|
||||
datasets: [
|
||||
{
|
||||
label: "Stock Open Price",
|
||||
data: historicalStockQuoteChartData.value
|
||||
}
|
||||
]
|
||||
}}
|
||||
options={{
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: "Time"
|
||||
},
|
||||
ticks: {
|
||||
callback: function(value, index, ticks) {
|
||||
return (new Date(value as number*1000)).toISOString().substring(0,10);
|
||||
}
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: false,
|
||||
ticks: {
|
||||
callback: function(value, index, ticks) {
|
||||
return "$"+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,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
: <div>Loading Chart...</div>}
|
||||
</div>
|
||||
<div className="chart-container">
|
||||
{chosenUnderlying.value!==null && historicalCalendarQuoteChartData.value.length>0
|
||||
? <div className="chart">
|
||||
<Scatter
|
||||
data={{
|
||||
datasets: [
|
||||
{
|
||||
label: "Calendar Open Price",
|
||||
data: historicalCalendarQuoteChartData.value
|
||||
}
|
||||
]
|
||||
}}
|
||||
options={{
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: "Time"
|
||||
},
|
||||
ticks: {
|
||||
callback: function(value, index, ticks) {
|
||||
return (new Date(value as number*1000)).toISOString().substring(0,10);
|
||||
}
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: function(value, index, ticks) {
|
||||
return "$"+value.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: "Calendar Price (Under Like Conditions)"
|
||||
},
|
||||
},
|
||||
animation: false,
|
||||
maintainAspectRatio: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
: <div>Loading Chart...</div>}
|
||||
|
||||
{chosenUnderlying.value!==null && historicalCalendarQuoteChartData.value.length>0
|
||||
? <div className="chart">
|
||||
<Scatter
|
||||
data={{
|
||||
datasets: [
|
||||
{
|
||||
label: "Calendar Exit Price",
|
||||
data: historicalCalendarExitQuoteChartData.value
|
||||
}
|
||||
]
|
||||
}}
|
||||
options={{
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear',
|
||||
beginAtZero: false,
|
||||
title: {
|
||||
display: true,
|
||||
text: "%-From-the-Money"
|
||||
},
|
||||
ticks: {
|
||||
callback: function(value, index, ticks) {
|
||||
return value.toString()+"%";
|
||||
}
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: function(value, index, ticks) {
|
||||
return "$"+value.toString();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
borderWidth: 0,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: ["Calendar Prices at Exit","by %-age from-the-money"]
|
||||
},
|
||||
},
|
||||
animation: false,
|
||||
maintainAspectRatio: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
: <div>Loading Chart...</div>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.chart-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-around;
|
||||
width: 1800px;
|
||||
height: 480px;
|
||||
}
|
||||
.chart-container > .chart {
|
||||
width: 880px;
|
||||
}
|
||||
Reference in New Issue
Block a user