|
|
|
@ -1,13 +1,13 @@
|
|
|
|
|
import type { CalendarDatabase, CalendarKey } from "./interfaces.js";
|
|
|
|
|
import type { Aggregate } from "../interfaces.js";
|
|
|
|
|
import { query } from "../lib/clickhouse.js";
|
|
|
|
|
import { query } from "../../lib/clickhouse.js";
|
|
|
|
|
|
|
|
|
|
function makeCalendarDatabase(): CalendarDatabase {
|
|
|
|
|
const calendarDatabase: Omit<CalendarDatabase, "getCalendars"> = {
|
|
|
|
|
getKeys: async ({ key: { symbol }, date }) => {
|
|
|
|
|
const calendarsForSymbolOnDate = await query<
|
|
|
|
|
Omit<CalendarKey, "symbol">
|
|
|
|
|
>(`
|
|
|
|
|
const calendarDatabase: Omit<CalendarDatabase, "getCalendars"> = {
|
|
|
|
|
getKeys: async ({ key: { symbol }, date }) => {
|
|
|
|
|
const calendarsForSymbolOnDate = await query<
|
|
|
|
|
Omit<CalendarKey, "symbol">
|
|
|
|
|
>(`
|
|
|
|
|
WITH today_option_contracts AS (
|
|
|
|
|
SELECT expirationDate, strike, type
|
|
|
|
|
FROM option_contract_existences
|
|
|
|
@ -26,17 +26,66 @@ function makeCalendarDatabase(): CalendarDatabase {
|
|
|
|
|
AND front_option_contract.expirationDate < back_option_contract.expirationDate
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
return calendarsForSymbolOnDate.map((calendarWithoutSymbol) => ({
|
|
|
|
|
...calendarWithoutSymbol,
|
|
|
|
|
symbol,
|
|
|
|
|
}));
|
|
|
|
|
},
|
|
|
|
|
getAggregates: async ({
|
|
|
|
|
key: { symbol, frontExpirationDate, backExpirationDate, strike, type },
|
|
|
|
|
date,
|
|
|
|
|
}) => {
|
|
|
|
|
return (
|
|
|
|
|
await query<Omit<Aggregate<CalendarKey>, "key">>(`
|
|
|
|
|
return calendarsForSymbolOnDate.map((calendarWithoutSymbol) => ({
|
|
|
|
|
...calendarWithoutSymbol,
|
|
|
|
|
symbol,
|
|
|
|
|
}));
|
|
|
|
|
},
|
|
|
|
|
getAggregate: async ({
|
|
|
|
|
key: { symbol, frontExpirationDate, backExpirationDate, strike, type },
|
|
|
|
|
tsStart,
|
|
|
|
|
}) => {
|
|
|
|
|
const tsStartString = new Date(tsStart).toISOString();
|
|
|
|
|
return (
|
|
|
|
|
await query<Omit<Aggregate<CalendarKey>, "key">>(`
|
|
|
|
|
WITH front_option_contract_candlestick AS (
|
|
|
|
|
SELECT
|
|
|
|
|
tsStart,
|
|
|
|
|
open,
|
|
|
|
|
close,
|
|
|
|
|
high,
|
|
|
|
|
low
|
|
|
|
|
FROM option_contract_aggregates
|
|
|
|
|
WHERE symbol = '${symbol}'
|
|
|
|
|
AND type = '${type}'
|
|
|
|
|
AND strike = '${strike}'
|
|
|
|
|
AND expirationDate = '${frontExpirationDate}'
|
|
|
|
|
AND tsStart = '${tsStartString}'
|
|
|
|
|
),
|
|
|
|
|
back_option_contract_candlestick AS (
|
|
|
|
|
SELECT
|
|
|
|
|
tsStart,
|
|
|
|
|
open,
|
|
|
|
|
close,
|
|
|
|
|
high,
|
|
|
|
|
low
|
|
|
|
|
FROM option_contract_aggregates
|
|
|
|
|
WHERE symbol = '${symbol}'
|
|
|
|
|
AND type = '${type}'
|
|
|
|
|
AND strike = '${strike}'
|
|
|
|
|
AND expirationDate = '${backExpirationDate}'
|
|
|
|
|
AND tsStart = '${tsStartString}'
|
|
|
|
|
)
|
|
|
|
|
SELECT
|
|
|
|
|
toUnixTimestamp(front_option_contract_candlestick.tsStart) as tsStart,
|
|
|
|
|
back_option_contract_candlestick.open - front_option_contract_candlestick.open as open,
|
|
|
|
|
back_option_contract_candlestick.close - front_option_contract_candlestick.close as close
|
|
|
|
|
FROM front_option_contract_candlestick
|
|
|
|
|
INNER JOIN back_option_contract_candlestick
|
|
|
|
|
ON front_option_contract_candlestick.tsStart = back_option_contract_candlestick.tsStart
|
|
|
|
|
ORDER BY front_option_contract_candlestick.tsStart ASC
|
|
|
|
|
`)
|
|
|
|
|
).map((aggregate) => ({
|
|
|
|
|
...aggregate,
|
|
|
|
|
tsStart: aggregate.tsStart * 1000, // unfortunately, `toUnixTimestamp` only returns second-precision
|
|
|
|
|
}))[0];
|
|
|
|
|
},
|
|
|
|
|
getAggregates: async ({
|
|
|
|
|
key: { symbol, frontExpirationDate, backExpirationDate, strike, type },
|
|
|
|
|
date,
|
|
|
|
|
}) => {
|
|
|
|
|
return (
|
|
|
|
|
await query<Omit<Aggregate<CalendarKey>, "key">>(`
|
|
|
|
|
WITH front_option_contract_candlestick AS (
|
|
|
|
|
SELECT
|
|
|
|
|
tsStart,
|
|
|
|
@ -74,19 +123,19 @@ function makeCalendarDatabase(): CalendarDatabase {
|
|
|
|
|
ON front_option_contract_candlestick.tsStart = back_option_contract_candlestick.tsStart
|
|
|
|
|
ORDER BY front_option_contract_candlestick.tsStart ASC
|
|
|
|
|
`)
|
|
|
|
|
).map((aggregate) => ({
|
|
|
|
|
...aggregate,
|
|
|
|
|
tsStart: aggregate.tsStart * 1000, // unfortunately, `toUnixTimestamp` only returns second-precision
|
|
|
|
|
}));
|
|
|
|
|
},
|
|
|
|
|
insertAggregates: async (aggregates) => {
|
|
|
|
|
// no-op: we insert individual option contracts, not calendars
|
|
|
|
|
},
|
|
|
|
|
getClosingPrice: async ({
|
|
|
|
|
key: { symbol, strike, type, frontExpirationDate, backExpirationDate },
|
|
|
|
|
}) => {
|
|
|
|
|
return (
|
|
|
|
|
await query<{ calendarClosingPrice: number }>(`
|
|
|
|
|
).map((aggregate) => ({
|
|
|
|
|
...aggregate,
|
|
|
|
|
tsStart: aggregate.tsStart * 1000, // unfortunately, `toUnixTimestamp` only returns second-precision
|
|
|
|
|
}));
|
|
|
|
|
},
|
|
|
|
|
insertAggregates: async (aggregates) => {
|
|
|
|
|
// no-op: we insert individual option contracts, not calendars
|
|
|
|
|
},
|
|
|
|
|
getClosingPrice: async ({
|
|
|
|
|
key: { symbol, strike, type, frontExpirationDate, backExpirationDate },
|
|
|
|
|
}) => {
|
|
|
|
|
return (
|
|
|
|
|
await query<{ calendarClosingPrice: number }>(`
|
|
|
|
|
WITH front_option_contract_candlestick AS (
|
|
|
|
|
SELECT
|
|
|
|
|
tsStart,
|
|
|
|
@ -121,22 +170,22 @@ function makeCalendarDatabase(): CalendarDatabase {
|
|
|
|
|
INNER JOIN back_option_contract_candlestick
|
|
|
|
|
ON front_option_contract_candlestick.tsStart = back_option_contract_candlestick.tsStart
|
|
|
|
|
`)
|
|
|
|
|
)[0]?.calendarClosingPrice;
|
|
|
|
|
},
|
|
|
|
|
getTargetPriceByProbability: async ({
|
|
|
|
|
symbol,
|
|
|
|
|
calendarSpan,
|
|
|
|
|
strikePercentageFromTheMoney,
|
|
|
|
|
historicalProbabilityOfSuccess,
|
|
|
|
|
}) => {
|
|
|
|
|
return 0.24;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
)[0]?.calendarClosingPrice;
|
|
|
|
|
},
|
|
|
|
|
getTargetPriceByProbability: async ({
|
|
|
|
|
symbol,
|
|
|
|
|
calendarSpan,
|
|
|
|
|
strikePercentageFromTheMoney,
|
|
|
|
|
historicalProbabilityOfSuccess,
|
|
|
|
|
}) => {
|
|
|
|
|
return 0.24;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...calendarDatabase,
|
|
|
|
|
getCalendars: calendarDatabase.getKeys,
|
|
|
|
|
};
|
|
|
|
|
return {
|
|
|
|
|
...calendarDatabase,
|
|
|
|
|
getCalendars: calendarDatabase.getKeys,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const calendarDatabase: CalendarDatabase = makeCalendarDatabase();
|