@ -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 < 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 ;
} ,
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 ,
@ -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 ( ) ;