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.
167 lines
4.4 KiB
TypeScript
167 lines
4.4 KiB
TypeScript
import type { CalendarDatabase } from "./interfaces.js";
|
|
import { open } from "lmdbx";
|
|
|
|
const calendarAggregatesDb = open({
|
|
path: "./calendar-aggregates.db",
|
|
compression: true,
|
|
});
|
|
|
|
const calendarExistenceDb = open({
|
|
path: "./calendar-existence.db",
|
|
compression: true,
|
|
});
|
|
|
|
/** Largest possible key according to the `ordered-binary` (used by lmdbx) docs. */
|
|
const MAXIMUM_KEY = Buffer.from([0xff]);
|
|
|
|
function makeCalendarDatabase(): CalendarDatabase {
|
|
const calendarDatabase: Omit<CalendarDatabase, "getCalendars"> = {
|
|
getKeys: async ({ key: { symbol }, date }) => {
|
|
return calendarExistenceDb
|
|
.getRange({
|
|
start: [date, symbol],
|
|
end: [date, symbol, MAXIMUM_KEY],
|
|
})
|
|
.map(({ key }) => ({
|
|
symbol,
|
|
frontExpirationDate: key[2],
|
|
backExpirationDate: key[3],
|
|
strike: key[4],
|
|
type: key[5],
|
|
})).asArray;
|
|
},
|
|
getAggregates: async ({
|
|
key: { symbol, frontExpirationDate, backExpirationDate, strike, type },
|
|
date,
|
|
}) => {
|
|
const startOfDayUnix = new Date(`${date}T00:00:00Z`).valueOf();
|
|
const endOfDayUnix = startOfDayUnix + 3600 * 24 * 1000;
|
|
return calendarAggregatesDb
|
|
.getRange({
|
|
start: [
|
|
symbol,
|
|
frontExpirationDate,
|
|
backExpirationDate,
|
|
strike,
|
|
type,
|
|
startOfDayUnix,
|
|
],
|
|
end: [
|
|
symbol,
|
|
frontExpirationDate,
|
|
backExpirationDate,
|
|
strike,
|
|
type,
|
|
endOfDayUnix,
|
|
],
|
|
})
|
|
.map(({ value }) => ({
|
|
tsStart: value.tsStart,
|
|
open: value.open,
|
|
close: value.close,
|
|
high: value.high,
|
|
low: value.low,
|
|
})).asArray;
|
|
},
|
|
getAggregate: async ({
|
|
key: { symbol, frontExpirationDate, backExpirationDate, strike, type },
|
|
tsStart,
|
|
}) => {
|
|
return await calendarAggregatesDb.get([
|
|
symbol,
|
|
frontExpirationDate,
|
|
backExpirationDate,
|
|
strike,
|
|
type,
|
|
tsStart,
|
|
]);
|
|
},
|
|
insertAggregates: async (aggregates) => {
|
|
await calendarExistenceDb.batch(() => {
|
|
for (const aggregate of aggregates) {
|
|
calendarExistenceDb.put(
|
|
[
|
|
new Date(aggregate.tsStart).toISOString().substring(0, 10),
|
|
aggregate.key.symbol,
|
|
aggregate.key.frontExpirationDate,
|
|
aggregate.key.backExpirationDate,
|
|
aggregate.key.strike,
|
|
aggregate.key.type,
|
|
],
|
|
null
|
|
);
|
|
}
|
|
});
|
|
await calendarAggregatesDb.batch(() => {
|
|
for (const aggregate of aggregates) {
|
|
calendarAggregatesDb.put(
|
|
[
|
|
aggregate.key.symbol,
|
|
aggregate.key.frontExpirationDate,
|
|
aggregate.key.backExpirationDate,
|
|
aggregate.key.strike,
|
|
aggregate.key.type,
|
|
aggregate.tsStart,
|
|
],
|
|
{
|
|
open: aggregate.open,
|
|
close: aggregate.close,
|
|
high: aggregate.high,
|
|
low: aggregate.low,
|
|
}
|
|
);
|
|
}
|
|
});
|
|
},
|
|
getClosingPrice: async ({
|
|
key: { symbol, strike, type, frontExpirationDate, backExpirationDate },
|
|
}) => {
|
|
const startOfExpirationDateUnix = new Date(
|
|
`${frontExpirationDate}T23:59:59Z`
|
|
).valueOf();
|
|
const endOfExpirationDateUnix = new Date(
|
|
`${frontExpirationDate}T00:00:00Z`
|
|
).valueOf();
|
|
for (const { value } of calendarAggregatesDb.getRange({
|
|
start: [
|
|
symbol,
|
|
frontExpirationDate,
|
|
backExpirationDate,
|
|
strike,
|
|
type,
|
|
startOfExpirationDateUnix,
|
|
],
|
|
end: [
|
|
symbol,
|
|
frontExpirationDate,
|
|
backExpirationDate,
|
|
strike,
|
|
type,
|
|
endOfExpirationDateUnix,
|
|
],
|
|
reverse: true,
|
|
})) {
|
|
if (value.close > 0) {
|
|
return value.close;
|
|
}
|
|
}
|
|
return 0;
|
|
},
|
|
getTargetPriceByProbability: async ({
|
|
symbol,
|
|
calendarSpan,
|
|
strikePercentageFromTheMoney,
|
|
historicalProbabilityOfSuccess,
|
|
}) => {
|
|
return 0.24;
|
|
},
|
|
};
|
|
|
|
return {
|
|
...calendarDatabase,
|
|
getCalendars: calendarDatabase.getKeys,
|
|
};
|
|
}
|
|
|
|
export const calendarDatabase: CalendarDatabase = makeCalendarDatabase();
|