calendar optimizer page works
This commit is contained in:
@@ -1,6 +1,18 @@
|
|||||||
import { signal } from "@preact/signals";
|
import { signal } from "@preact/signals";
|
||||||
import { useCallback, useEffect } from "preact/hooks";
|
import { useCallback, useEffect } from "preact/hooks";
|
||||||
import { trpc } from "../../trpc.js";
|
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 availableUnderlyings = signal([]);
|
||||||
const chosenUnderlying = signal(null);
|
const chosenUnderlying = signal(null);
|
||||||
@@ -151,12 +163,143 @@ export function CalendarOptimizer() {
|
|||||||
</select>
|
</select>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* {chosenUnderlying.value!==null && underlyingUplotData.value.length>0
|
<div className="chart-container">
|
||||||
? <UPlot data={underlyingUplotData.value} title="Underlying" opts={uplotOpts}/>
|
{chosenUnderlying.value !== null &&
|
||||||
: <></>}
|
underlyingUplotData.value.length > 0 ? (
|
||||||
{chosenUnderlying.value!==null && chosenAsOfDate.value!==null && chosenExpiration.value!==null && chosenStrike.value!==null && optionContractUplotData.value.length>0
|
<div className="chart">
|
||||||
? <UPlot data={optionContractUplotData.value} title="Option Contract" opts={uplotOpts}/>
|
<Scatter
|
||||||
: <></>} */}
|
data={{
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Stock Open Price",
|
||||||
|
data: underlyingUplotData.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);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// min: (new Date(chosenLookbackPeriodStart.value)).getTime()/1000,
|
||||||
|
// max: (new Date(chosenLookbackPeriodEnd.value)).getTime()/1000,
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
beginAtZero: false,
|
||||||
|
ticks: {
|
||||||
|
callback: function (value, index, ticks) {
|
||||||
|
return "$" + value.toString();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// min: 0,
|
||||||
|
// max: maxChartPrice.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
point: {
|
||||||
|
radius: 1,
|
||||||
|
borderWidth: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
tooltip: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Stock Price",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: false,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
{chosenUnderlying.value !== null &&
|
||||||
|
chosenAsOfDate.value !== null &&
|
||||||
|
chosenExpiration.value !== null &&
|
||||||
|
chosenStrike.value !== null &&
|
||||||
|
optionContractUplotData.value.length > 0 ? (
|
||||||
|
<div className="chart">
|
||||||
|
<Scatter
|
||||||
|
data={{
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Option Contract Open Price",
|
||||||
|
data: optionContractUplotData.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);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// min: (new Date(chosenLookbackPeriodStart.value)).getTime()/1000,
|
||||||
|
// max: (new Date(chosenLookbackPeriodEnd.value)).getTime()/1000,
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
beginAtZero: false,
|
||||||
|
ticks: {
|
||||||
|
callback: function (value, index, ticks) {
|
||||||
|
return "$" + value.toString();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// min: 0,
|
||||||
|
// max: maxChartPrice.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
point: {
|
||||||
|
radius: 1,
|
||||||
|
borderWidth: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
tooltip: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Option Contract Price",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: false,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</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;
|
||||||
|
}
|
||||||
+15
-30
@@ -49,6 +49,7 @@ const appRouter = router({
|
|||||||
DISTINCT(asOfDate) as asOfDate
|
DISTINCT(asOfDate) as asOfDate
|
||||||
FROM option_contracts
|
FROM option_contracts
|
||||||
WHERE symbol = '${underlying}'
|
WHERE symbol = '${underlying}'
|
||||||
|
ORDER BY asOfDate
|
||||||
`)
|
`)
|
||||||
).map(({ asOfDate }) => asOfDate);
|
).map(({ asOfDate }) => asOfDate);
|
||||||
}),
|
}),
|
||||||
@@ -66,10 +67,11 @@ const appRouter = router({
|
|||||||
return (
|
return (
|
||||||
await query<{ expirationDate: string }>(`
|
await query<{ expirationDate: string }>(`
|
||||||
SELECT
|
SELECT
|
||||||
DISTINCT(expirationDate)
|
DISTINCT(expirationDate) as expirationDate
|
||||||
FROM option_contracts
|
FROM option_contracts
|
||||||
WHERE symbol = '${underlying}'
|
WHERE symbol = '${underlying}'
|
||||||
AND asOfDate = '${asOfDate}'
|
AND asOfDate = '${asOfDate}'
|
||||||
|
ORDER BY expirationDate
|
||||||
`)
|
`)
|
||||||
).map(({ expirationDate }) => expirationDate);
|
).map(({ expirationDate }) => expirationDate);
|
||||||
}),
|
}),
|
||||||
@@ -88,11 +90,12 @@ const appRouter = router({
|
|||||||
return (
|
return (
|
||||||
await query<{ strike: string }>(`
|
await query<{ strike: string }>(`
|
||||||
SELECT
|
SELECT
|
||||||
DISTINCT(strike)
|
DISTINCT(strike) as strike
|
||||||
FROM option_contracts
|
FROM option_contracts
|
||||||
WHERE symbol = '${underlying}'
|
WHERE symbol = '${underlying}'
|
||||||
AND asOfDate = '${asOfDate}'
|
AND asOfDate = '${asOfDate}'
|
||||||
AND expirationDate = '${expirationDate}'
|
AND expirationDate = '${expirationDate}'
|
||||||
|
ORDER BY strike
|
||||||
`)
|
`)
|
||||||
).map(({ strike }) => strike);
|
).map(({ strike }) => strike);
|
||||||
}),
|
}),
|
||||||
@@ -106,25 +109,16 @@ const appRouter = router({
|
|||||||
)
|
)
|
||||||
.query(async (opts) => {
|
.query(async (opts) => {
|
||||||
const { underlying } = opts.input;
|
const { underlying } = opts.input;
|
||||||
return (
|
return await query<{ x: number; y: number }>(
|
||||||
await query<[number, number]>(
|
`
|
||||||
`
|
|
||||||
SELECT
|
SELECT
|
||||||
toUnixTimestamp(tsStart),
|
toUnixTimestamp(tsStart) as x,
|
||||||
open
|
open as y
|
||||||
FROM stock_aggregates
|
FROM stock_aggregates
|
||||||
WHERE symbol = '${underlying}'
|
WHERE symbol = '${underlying}'
|
||||||
ORDER BY tsStart ASC
|
ORDER BY tsStart ASC
|
||||||
`,
|
`,
|
||||||
"JSONCompactEachRow"
|
"JSONEachRow"
|
||||||
)
|
|
||||||
).reduce(
|
|
||||||
(columns, row) => {
|
|
||||||
columns[0].push(row[0]);
|
|
||||||
columns[1].push(row[1]);
|
|
||||||
return columns;
|
|
||||||
},
|
|
||||||
[[], []]
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
getOpensForOptionContract: publicProcedure
|
getOpensForOptionContract: publicProcedure
|
||||||
@@ -139,12 +133,11 @@ const appRouter = router({
|
|||||||
)
|
)
|
||||||
.query(async (opts) => {
|
.query(async (opts) => {
|
||||||
const { underlying, expirationDate, strike } = opts.input;
|
const { underlying, expirationDate, strike } = opts.input;
|
||||||
return (
|
return await query<{ x: number; y: number }>(
|
||||||
await query<[number, number]>(
|
`
|
||||||
`
|
|
||||||
SELECT
|
SELECT
|
||||||
toUnixTimestamp(tsStart),
|
toUnixTimestamp(tsStart) as x,
|
||||||
open
|
open as y
|
||||||
FROM option_aggregates
|
FROM option_aggregates
|
||||||
WHERE symbol = '${underlying}'
|
WHERE symbol = '${underlying}'
|
||||||
AND expirationDate = '${expirationDate}'
|
AND expirationDate = '${expirationDate}'
|
||||||
@@ -152,15 +145,7 @@ const appRouter = router({
|
|||||||
AND type = 'call'
|
AND type = 'call'
|
||||||
ORDER BY tsStart ASC
|
ORDER BY tsStart ASC
|
||||||
`,
|
`,
|
||||||
"JSONCompactEachRow"
|
"JSONEachRow"
|
||||||
)
|
|
||||||
).reduce(
|
|
||||||
(columns, row) => {
|
|
||||||
columns[0].push(row[0]);
|
|
||||||
columns[1].push(row[1]);
|
|
||||||
return columns;
|
|
||||||
},
|
|
||||||
[[], []]
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
getHistoricalCalendarPrices: publicProcedure
|
getHistoricalCalendarPrices: publicProcedure
|
||||||
|
|||||||
Reference in New Issue
Block a user