You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
2.4 KiB
TypeScript
91 lines
2.4 KiB
TypeScript
import type {
|
|
OptionContractDatabase,
|
|
OptionContractKey,
|
|
} from "./optiondb.interfaces.js";
|
|
import type { Aggregate } from "./interfaces.js";
|
|
import { clickhouse, query } from "./lib/clickhouse.js";
|
|
|
|
function makeOptionContractDatabase(): OptionContractDatabase {
|
|
const optionContractDatabase: Omit<
|
|
OptionContractDatabase,
|
|
"getOptionContracts"
|
|
> = {
|
|
getKeys: async ({ key: { symbol }, date }) => {
|
|
return (
|
|
await query<Omit<OptionContractKey, "symbol">>(`
|
|
SELECT expirationDate, strike, type
|
|
FROM option_contract_existences
|
|
WHERE symbol = '${symbol}'
|
|
AND asOfDate = '${date}'
|
|
`)
|
|
).map((optionContractWithoutKey) => ({
|
|
...optionContractWithoutKey,
|
|
symbol,
|
|
}));
|
|
},
|
|
getAggregates: async ({
|
|
key: { symbol, expirationDate, strike, type },
|
|
date,
|
|
}) => {
|
|
return (
|
|
await query<Omit<Aggregate<OptionContractKey>, "key">>(`
|
|
SELECT
|
|
toUnixTimestamp(tsStart) as tsStart,
|
|
open,
|
|
close,
|
|
high,
|
|
low
|
|
FROM option_contract_aggregates
|
|
WHERE symbol = '${symbol}'
|
|
AND type = '${type}'
|
|
AND strike = '${strike}'
|
|
AND expirationDate = '${expirationDate}'
|
|
AND toDate(tsStart) = '${date}'
|
|
ORDER BY tsStart ASC
|
|
`)
|
|
).map((aggregate) => ({
|
|
...aggregate,
|
|
tsStart: aggregate.tsStart * 1000, // unfortunately, `toUnixTimestamp` only returns second-precision
|
|
}));
|
|
},
|
|
insertAggregates: async (aggregates) => {
|
|
// stock existence is taken care of by clickhouse materialized view
|
|
await clickhouse.insert({
|
|
table: "option_contract_aggregates",
|
|
values: aggregates.map(
|
|
({
|
|
key: { symbol, expirationDate, strike, type },
|
|
tsStart,
|
|
open,
|
|
close,
|
|
high,
|
|
low,
|
|
}) => ({
|
|
symbol,
|
|
expirationDate,
|
|
strike,
|
|
type,
|
|
tsStart,
|
|
open,
|
|
close,
|
|
high,
|
|
low,
|
|
}),
|
|
),
|
|
});
|
|
},
|
|
getClosingPrice: async ({ key }) => {
|
|
// no-op: not used since stocks don't have a "closing" price, unlike options.
|
|
return 0;
|
|
},
|
|
};
|
|
|
|
return {
|
|
...optionContractDatabase,
|
|
getOptionContracts: optionContractDatabase.getKeys,
|
|
};
|
|
}
|
|
|
|
export const optionContractDatabase: OptionContractDatabase =
|
|
makeOptionContractDatabase();
|