From 8d908521fd840ab5a29741300970832badec6096 Mon Sep 17 00:00:00 2001 From: avraham Date: Sun, 11 Aug 2024 17:36:31 -0400 Subject: [PATCH] fix: `getClosingPrice()` for two calendardb modules --- server/src/calendardb/lmdbx.ts | 266 ++++++++++++------------ server/src/calendardb/optiondb-lmdbx.ts | 11 +- 2 files changed, 140 insertions(+), 137 deletions(-) diff --git a/server/src/calendardb/lmdbx.ts b/server/src/calendardb/lmdbx.ts index b9d1626..4923093 100644 --- a/server/src/calendardb/lmdbx.ts +++ b/server/src/calendardb/lmdbx.ts @@ -2,67 +2,67 @@ import type { CalendarDatabase } from "./interfaces.js"; import { open } from "lmdbx"; const calendarAggregatesDb = open({ - path: "./calendar-aggregates.db", - compression: true, + path: "./calendar-aggregates.db", + compression: true, }); const calendarExistenceDb = open({ - path: "./calendar-existence.db", - compression: true, + 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 = { - 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; - }, + const calendarDatabase: Omit = { + 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, @@ -76,89 +76,91 @@ function makeCalendarDatabase(): CalendarDatabase { 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, - ], + 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, + ); + } + }); + 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 startOfLastHourUnix = new Date( - `${frontExpirationDate}T00:00:00Z`, - ).valueOf(); - const endOfLastHourUnix = startOfLastHourUnix + 3600 * 1000; - let minPrice = 0; - for (const { value } of calendarAggregatesDb.getRange({ - start: [ - symbol, - frontExpirationDate, - backExpirationDate, - strike, - type, - startOfLastHourUnix, - ], - end: [ - symbol, - frontExpirationDate, - backExpirationDate, - strike, - type, - endOfLastHourUnix, - ], - })) { - if (value.close < minPrice || minPrice === 0) { - minPrice = value.close; - } - } - return minPrice; - }, - getTargetPriceByProbability: async ({ - symbol, - calendarSpan, - strikePercentageFromTheMoney, - historicalProbabilityOfSuccess, - }) => { - return 0.24; - }, - }; + ); + } + }); + }, + 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, - }; + return { + ...calendarDatabase, + getCalendars: calendarDatabase.getKeys, + }; } export const calendarDatabase: CalendarDatabase = makeCalendarDatabase(); diff --git a/server/src/calendardb/optiondb-lmdbx.ts b/server/src/calendardb/optiondb-lmdbx.ts index f944280..60af0c9 100644 --- a/server/src/calendardb/optiondb-lmdbx.ts +++ b/server/src/calendardb/optiondb-lmdbx.ts @@ -93,9 +93,10 @@ function makeCalendarDatabase(): CalendarDatabase { getClosingPrice: async ({ key: { symbol, strike, type, frontExpirationDate, backExpirationDate }, }) => { + // get unix timestamp, in milliseconds, of the start of the last hour, which is 03:30PM in the `America/New_York` timezone on the front expiration date: const startOfLastHourUnix = new Date( - `${frontExpirationDate}T00:00:00Z`, - ).valueOf(); + `${frontExpirationDate}T19:30:00Z` + ).getTime(); const endOfLastHourUnix = startOfLastHourUnix + 3600 * 1000; const frontOptionContractAggregates = ( await optionContractDatabase.getAggregates({ @@ -104,7 +105,7 @@ function makeCalendarDatabase(): CalendarDatabase { }) ).filter( ({ tsStart }) => - tsStart >= startOfLastHourUnix && tsStart < endOfLastHourUnix, + tsStart >= startOfLastHourUnix && tsStart < endOfLastHourUnix ); const backOptionContractAggregates = ( await optionContractDatabase.getAggregates({ @@ -113,7 +114,7 @@ function makeCalendarDatabase(): CalendarDatabase { }) ).filter( ({ tsStart }) => - tsStart >= startOfLastHourUnix && tsStart < endOfLastHourUnix, + tsStart >= startOfLastHourUnix && tsStart < endOfLastHourUnix ); let i = 0; let j = 0; @@ -128,7 +129,7 @@ function makeCalendarDatabase(): CalendarDatabase { ) { const calendarClosePrice = backOptionContractAggregates[j].close - - frontOptionContractAggregates[j].close; + frontOptionContractAggregates[i].close; if (calendarClosePrice < minPrice || minPrice === 0) { minPrice = calendarClosePrice; }