Compare commits

...

2 Commits

Author SHA1 Message Date
avraham eba5344b15 fix biome kvetches 2024-08-02 17:00:35 -04:00
avraham 39bb6c85f8 fix biome kvetches 2024-08-02 17:00:01 -04:00
5 changed files with 629 additions and 621 deletions
+10 -9
View File
@@ -86,7 +86,7 @@ function chooseStrike(strike: string) {
.query({
underlying: chosenUnderlying.value,
expirationDate: chosenExpiration.value,
strike: parseFloat(strike),
strike: Number.parseFloat(strike),
})
.then((getOpensForOptionContractResponse) => {
optionContractUplotData.value = getOpensForOptionContractResponse;
@@ -201,8 +201,9 @@ export function CalendarOptimizer() {
</Paper>
</Grid>
<Grid item xs={12} md={6}>
<Paper elevation={3} sx={{ p: 3, height: '100%' }}>
{chosenUnderlying.value !== null && underlyingUplotData.value.length > 0 ? (
<Paper elevation={3} sx={{ p: 3, height: "100%" }}>
{chosenUnderlying.value !== null &&
underlyingUplotData.value.length > 0 ? (
<Scatter
data={{
datasets: [
@@ -220,7 +221,7 @@ export function CalendarOptimizer() {
text: "Time",
},
ticks: {
callback: function (value, index, ticks) {
callback: (value, index, ticks) => {
return new Date((value as number) * 1000)
.toISOString()
.substring(0, 10);
@@ -230,8 +231,8 @@ export function CalendarOptimizer() {
y: {
beginAtZero: false,
ticks: {
callback: function (value, index, ticks) {
return "$" + value.toString();
callback: (value, index, ticks) => {
return `$${value.toString()}`;
},
},
},
@@ -287,7 +288,7 @@ export function CalendarOptimizer() {
text: "Time",
},
ticks: {
callback: function (value, index, ticks) {
callback: (value, index, ticks) => {
return new Date((value as number) * 1000)
.toISOString()
.substring(0, 10);
@@ -297,8 +298,8 @@ export function CalendarOptimizer() {
y: {
beginAtZero: false,
ticks: {
callback: function (value, index, ticks) {
return "$" + value.toString();
callback: (value, index, ticks) => {
return `$${value.toString()}`;
},
},
},
+53 -46
View File
@@ -49,20 +49,20 @@ const maxChartPrice = computed(() =>
Math.max(
Math.max.apply(
null,
historicalCalendarQuoteChartData.value.map((d) => d.y)
historicalCalendarQuoteChartData.value.map((d) => d.y),
),
Math.max.apply(
null,
historicalCalendarExitQuoteChartData.value.map((d) => d.y)
)
)
historicalCalendarExitQuoteChartData.value.map((d) => d.y),
),
),
);
const maxN = computed(() =>
Math.max.apply(
null,
historicalCalendarExitQuoteChartData.value.map((d) => d.n)
)
historicalCalendarExitQuoteChartData.value.map((d) => d.n),
),
);
const refreshHistoricalStockQuoteChartData = () => {
@@ -134,16 +134,19 @@ const handleUnderlyingChange = (e) => {
}
};
const handleDaysToFrontExpirationChange = (e) => {
if (chosenDaysToFrontExpiration.value !== parseInt(e.target.value)) {
chosenDaysToFrontExpiration.value = parseInt(e.target.value);
if (chosenDaysToFrontExpiration.value !== Number.parseInt(e.target.value)) {
chosenDaysToFrontExpiration.value = Number.parseInt(e.target.value);
refreshHistoricalCalendarQuoteChartData();
}
};
const handleDaysBetweenFrontAndBackExpirationChange = (e) => {
if (
chosenDaysBetweenFrontAndBackExpiration.value !== parseInt(e.target.value)
chosenDaysBetweenFrontAndBackExpiration.value !==
Number.parseInt(e.target.value)
) {
chosenDaysBetweenFrontAndBackExpiration.value = parseInt(e.target.value);
chosenDaysBetweenFrontAndBackExpiration.value = Number.parseInt(
e.target.value,
);
refreshHistoricalCalendarQuoteChartData();
refreshHistoricalCalendarExitQuoteChartData();
}
@@ -151,10 +154,10 @@ const handleDaysBetweenFrontAndBackExpirationChange = (e) => {
const handleStrikePercentageFromUnderlyingPriceChange = (e) => {
if (
chosenStrikePercentageFromUnderlyingPrice.value !==
parseFloat(e.target.value)
Number.parseFloat(e.target.value)
) {
chosenStrikePercentageFromUnderlyingPrice.value = parseFloat(
e.target.value
chosenStrikePercentageFromUnderlyingPrice.value = Number.parseFloat(
e.target.value,
);
refreshHistoricalCalendarQuoteChartData();
}
@@ -162,17 +165,17 @@ const handleStrikePercentageFromUnderlyingPriceChange = (e) => {
const handleStrikePercentageFromUnderlyingPriceRadiusChange = (e) => {
if (
chosenStrikePercentageFromUnderlyingPriceRadius.value !==
parseFloat(e.target.value)
Number.parseFloat(e.target.value)
) {
chosenStrikePercentageFromUnderlyingPriceRadius.value = parseFloat(
e.target.value
chosenStrikePercentageFromUnderlyingPriceRadius.value = Number.parseFloat(
e.target.value,
);
refreshHistoricalCalendarQuoteChartData();
}
};
const handleExitToFrontExpirationChange = (e) => {
if (chosenExitToFrontExpiration.value !== parseInt(e.target.value)) {
chosenExitToFrontExpiration.value = parseInt(e.target.value);
if (chosenExitToFrontExpiration.value !== Number.parseInt(e.target.value)) {
chosenExitToFrontExpiration.value = Number.parseInt(e.target.value);
refreshHistoricalCalendarExitQuoteChartData();
}
};
@@ -260,7 +263,9 @@ export function HistoricalCalendarPrices() {
label="Strike % Radius"
type="number"
value={chosenStrikePercentageFromUnderlyingPriceRadius.value}
onChange={handleStrikePercentageFromUnderlyingPriceRadiusChange}
onChange={
handleStrikePercentageFromUnderlyingPriceRadiusChange
}
InputProps={{ endAdornment: "%" }}
/>
</Grid>
@@ -280,25 +285,33 @@ export function HistoricalCalendarPrices() {
label="Lookback Period Start"
type="date"
value={chosenLookbackPeriodStart.value}
onChange={(e) => handleLookbackPeriodStartChange({ target: { value: e.target.value } })}
onChange={(e) =>
handleLookbackPeriodStartChange({
target: { value: e.target.value },
})
}
InputLabelProps={{ shrink: true }}
/>
</Grid>
<Grid item xs={6}>
</Grid>
<Grid item xs={6}>
<TextField
fullWidth
label="Lookback Period End"
type="date"
value={chosenLookbackPeriodEnd.value}
onChange={(e) => handleLookbackPeriodEndChange({ target: { value: e.target.value } })}
onChange={(e) =>
handleLookbackPeriodEndChange({
target: { value: e.target.value },
})
}
InputLabelProps={{ shrink: true }}
/>
</Grid>
</Grid>
</Grid>
</Paper>
</Grid>
<Grid item xs={12} md={6}>
<Paper elevation={3} sx={{ p: 3, height: '100%' }}>
<Paper elevation={3} sx={{ p: 3, height: "100%" }}>
{chosenUnderlying.value !== null &&
historicalStockQuoteChartData.value.length > 0 ? (
<Scatter
@@ -318,11 +331,10 @@ export function HistoricalCalendarPrices() {
text: "Time",
},
ticks: {
callback: function (value, index, ticks) {
return new Date((value as number) * 1000)
callback: (value, index, ticks) =>
new Date((value as number) * 1000)
.toISOString()
.substring(0, 10);
},
.substring(0, 10),
},
min:
new Date(chosenLookbackPeriodStart.value).getTime() /
@@ -334,9 +346,8 @@ export function HistoricalCalendarPrices() {
y: {
beginAtZero: false,
ticks: {
callback: function (value, index, ticks) {
return "$" + value.toString();
},
callback: (value, index, ticks) =>
`$${value.toString()}`,
},
},
},
@@ -389,11 +400,10 @@ export function HistoricalCalendarPrices() {
text: "Time",
},
ticks: {
callback: function (value, index, ticks) {
return new Date((value as number) * 1000)
callback: (value, index, ticks) =>
new Date((value as number) * 1000)
.toISOString()
.substring(0, 10);
},
.substring(0, 10),
},
min:
new Date(chosenLookbackPeriodStart.value).getTime() /
@@ -405,9 +415,8 @@ export function HistoricalCalendarPrices() {
y: {
beginAtZero: true,
ticks: {
callback: function (value, index, ticks) {
return "$" + value.toString();
},
callback: (value, index, ticks) =>
`$${value.toString()}`,
},
min: 0,
max: maxChartPrice.value,
@@ -458,17 +467,15 @@ export function HistoricalCalendarPrices() {
text: "%-From-the-Money",
},
ticks: {
callback: function (value, index, ticks) {
return value.toString() + "%";
},
callback: (value, index, ticks) =>
`${value.toString()}%`,
},
},
y: {
beginAtZero: true,
ticks: {
callback: function (value, index, ticks) {
return "$" + value.toString();
},
callback: (value, index, ticks) =>
`$${value.toString()}`,
},
min: 0,
max: maxChartPrice.value,
@@ -477,7 +484,7 @@ export function HistoricalCalendarPrices() {
elements: {
point: {
borderWidth: 0,
backgroundColor: function (context) {
backgroundColor: (context) => {
const n = (
context.raw as { x: number; y: number; n: number }
).n;
+7 -7
View File
@@ -48,7 +48,7 @@ export async function backtest({
...calendar,
},
date,
}),
})
);
}
// for each minute of that day for which we have a stock candlestick:
@@ -57,12 +57,12 @@ export async function backtest({
// filter-out calendars that are far-from-the-money (10%)
const calendarsNearTheMoney = calendars.filter(
({ strike }) =>
Math.abs((stockAggregate.open - strike) / stockAggregate.open) < 0.1,
Math.abs((stockAggregate.open - strike) / stockAggregate.open) < 0.1
);
// for each relevant calendar on that day:
for (const calendar of calendarsNearTheMoney) {
const strikePercentageFromTheMoney = Math.abs(
(stockAggregate.open - calendar.strike) / stockAggregate.open,
(stockAggregate.open - calendar.strike) / stockAggregate.open
);
/** In days. */
const calendarSpan =
@@ -78,14 +78,14 @@ export async function backtest({
});
const calendarAggregates = calendarsAggregates.get(calendar);
const calendarAggregateAtCurrentTime = calendarAggregates.find(
({ tsStart }) => tsStart === stockAggregate.tsStart,
({ tsStart }) => tsStart === stockAggregate.tsStart
);
// if there exists a matching calendar candlestick for the current minute:
if (calendarAggregateAtCurrentTime) {
// if the current candlestick is a good price (i.e. less than the target price):
const minCalendarPriceInCandlestick = Math.min(
calendarAggregateAtCurrentTime.open,
calendarAggregateAtCurrentTime.close,
calendarAggregateAtCurrentTime.close
);
if (
minCalendarPriceInCandlestick < targetCalendarPrice &&
@@ -104,7 +104,7 @@ export async function backtest({
minCalendarPriceInCandlestick * 100,
"...$",
buyingPower,
"left",
"left"
);
didBuyCalendar = true;
}
@@ -136,7 +136,7 @@ export async function backtest({
calendarClosingPrice,
"...$",
buyingPower,
"left",
"left"
);
}
}
+1 -1
View File
@@ -57,7 +57,7 @@ function makeCalendarDatabase(): CalendarDatabase {
close:
backOptionContractAggregates[j].close -
frontOptionContractAggregates[i].close,
// the high and low are not exactly correct since we don't know if each contract's high and low happened ata the same moment as the other:
// the high and low are not exactly correct since we don't know if each contract's high and low happened at the same moment as the other:
high:
backOptionContractAggregates[j].high -
frontOptionContractAggregates[i].high,
+1 -1
View File
@@ -17,7 +17,7 @@ async function syncAggregates<T>({
date: string;
}) {
const aggregatesFrom = (await fromDatabase.getAggregates({ key, date })).map(
(aggregateWithoutKey) => ({ ...aggregateWithoutKey, key }),
(aggregateWithoutKey) => ({ ...aggregateWithoutKey, key })
);
await toDatabase.insertAggregates(aggregatesFrom);
}