use lmdbx for stockdb in backtest, and limit to calendars within 5% of the money
This commit is contained in:
+24
-23
@@ -1,7 +1,6 @@
|
|||||||
import { stockDatabase } from "./stockdb/clickhouse.js";
|
import { stockDatabase } from "./stockdb/lmdbx.js";
|
||||||
import { calendarDatabase } from "./calendardb/optiondb-lmdbx.js";
|
import { calendarDatabase } from "./calendardb/optiondb-lmdbx.js";
|
||||||
import type { CalendarKey } from "./calendardb/interfaces.js";
|
import type { CalendarKey } from "./calendardb/interfaces.js";
|
||||||
import type { Aggregate } from "./interfaces.js";
|
|
||||||
import { nextDate } from "./lib/utils/nextDate.js";
|
import { nextDate } from "./lib/utils/nextDate.js";
|
||||||
|
|
||||||
type BacktestInput = {
|
type BacktestInput = {
|
||||||
@@ -38,49 +37,51 @@ export async function backtest({
|
|||||||
// for each minute of that day for which we have a stock candlestick:
|
// for each minute of that day for which we have a stock candlestick:
|
||||||
for (const stockAggregate of stockAggregates) {
|
for (const stockAggregate of stockAggregates) {
|
||||||
// console.log("Current Time:", new Date(stockAggregate.tsStart));
|
// console.log("Current Time:", new Date(stockAggregate.tsStart));
|
||||||
// filter-out calendars that are far-from-the-money (10%)
|
// filter-out calendars that are far-from-the-money (5%)
|
||||||
console.log("Current Date:", date, stockAggregate.tsStart);
|
|
||||||
const calendarsNearTheMoney = calendars.filter(
|
const calendarsNearTheMoney = calendars.filter(
|
||||||
({ strike }) =>
|
({ strike }) =>
|
||||||
Math.abs((stockAggregate.open - strike) / stockAggregate.open) < 0.1,
|
Math.abs((stockAggregate.open - strike) / stockAggregate.open) < 0.05
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Current Date:",
|
||||||
|
new Intl.DateTimeFormat("en-US", {
|
||||||
|
timeZone: "America/New_York",
|
||||||
|
dateStyle: "full",
|
||||||
|
timeStyle: "long",
|
||||||
|
}).format(new Date(stockAggregate.tsStart)),
|
||||||
|
";",
|
||||||
|
`${calendarsNearTheMoney.length} Calendars Near The Money`
|
||||||
);
|
);
|
||||||
// for each relevant calendar on that day:
|
// for each relevant calendar on that day:
|
||||||
for (const calendar of calendarsNearTheMoney) {
|
for (const calendar of calendarsNearTheMoney) {
|
||||||
const strikePercentageFromTheMoney = Math.abs(
|
const strikePercentageFromTheMoney = Math.abs(
|
||||||
(stockAggregate.open - calendar.strike) / stockAggregate.open,
|
(stockAggregate.open - calendar.strike) / stockAggregate.open
|
||||||
);
|
);
|
||||||
/** In days. */
|
/** Number of days between the back and front expiration dates. */
|
||||||
const calendarSpan =
|
const calendarSpanInDays =
|
||||||
(new Date(calendar.backExpirationDate).valueOf() -
|
(new Date(calendar.backExpirationDate).valueOf() -
|
||||||
new Date(calendar.frontExpirationDate).valueOf()) /
|
new Date(calendar.frontExpirationDate).valueOf()) /
|
||||||
(1000 * 60 * 60 * 24);
|
(1000 * 60 * 60 * 24);
|
||||||
const targetCalendarPrice =
|
const targetCalendarPrice =
|
||||||
await calendarDatabase.getTargetPriceByProbability({
|
await calendarDatabase.getTargetPriceByProbability({
|
||||||
symbol,
|
symbol,
|
||||||
calendarSpan,
|
calendarSpan: calendarSpanInDays,
|
||||||
strikePercentageFromTheMoney,
|
strikePercentageFromTheMoney,
|
||||||
historicalProbabilityOfSuccess,
|
historicalProbabilityOfSuccess,
|
||||||
});
|
});
|
||||||
const calendarAggregates = calendarDatabase.getAggregatesSync({
|
const calendarAggregateAtCurrentTime =
|
||||||
|
await calendarDatabase.getAggregate({
|
||||||
key: {
|
key: {
|
||||||
...calendar,
|
...calendar,
|
||||||
},
|
},
|
||||||
date,
|
tsStart: stockAggregate.tsStart,
|
||||||
});
|
});
|
||||||
// console.log(
|
|
||||||
// "Calendar Aggregates:",
|
|
||||||
// calendar,
|
|
||||||
// calendarAggregates.length,
|
|
||||||
// );
|
|
||||||
const calendarAggregateAtCurrentTime = calendarAggregates.find(
|
|
||||||
({ tsStart }) => tsStart === stockAggregate.tsStart,
|
|
||||||
);
|
|
||||||
// if there exists a matching calendar candlestick for the current minute:
|
// if there exists a matching calendar candlestick for the current minute:
|
||||||
if (calendarAggregateAtCurrentTime) {
|
if (calendarAggregateAtCurrentTime) {
|
||||||
// if the current candlestick is a good price (i.e. less than the target price):
|
// if the current candlestick is a good price (i.e. less than the target price):
|
||||||
const minCalendarPriceInCandlestick = Math.min(
|
const minCalendarPriceInCandlestick = Math.min(
|
||||||
calendarAggregateAtCurrentTime.open,
|
calendarAggregateAtCurrentTime.open,
|
||||||
calendarAggregateAtCurrentTime.close,
|
calendarAggregateAtCurrentTime.close
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
minCalendarPriceInCandlestick < targetCalendarPrice &&
|
minCalendarPriceInCandlestick < targetCalendarPrice &&
|
||||||
@@ -99,7 +100,7 @@ export async function backtest({
|
|||||||
minCalendarPriceInCandlestick * 100,
|
minCalendarPriceInCandlestick * 100,
|
||||||
"...$",
|
"...$",
|
||||||
buyingPower,
|
buyingPower,
|
||||||
"left",
|
"left"
|
||||||
);
|
);
|
||||||
didBuyCalendar = true;
|
didBuyCalendar = true;
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,7 @@ export async function backtest({
|
|||||||
calendarClosingPrice,
|
calendarClosingPrice,
|
||||||
"...$",
|
"...$",
|
||||||
buyingPower,
|
buyingPower,
|
||||||
"left",
|
"left"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user