From fa44e20069ba75f59312dd9d63b4bdeef28e02f5 Mon Sep 17 00:00:00 2001 From: Avraham Sakal Date: Wed, 5 Feb 2025 08:28:20 -0500 Subject: [PATCH] add "fill stock quoites" script, reorder scripts --- 01-ingest-stock-quotes.ts | 12 ++- 02-fill-stock-quotes.ts | 95 +++++++++++++++++++ ...on-quotes.ts => 03-ingest-option-quotes.ts | 0 ...tion-quotes.ts => 04-fill-option-quotes.ts | 0 ...-stats.ts => 05-populate-calendar-stats.ts | 0 5 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 02-fill-stock-quotes.ts rename 02-ingest-option-quotes.ts => 03-ingest-option-quotes.ts (100%) rename 03-fill-option-quotes.ts => 04-fill-option-quotes.ts (100%) rename 04-populate-calendar-stats.ts => 05-populate-calendar-stats.ts (100%) diff --git a/01-ingest-stock-quotes.ts b/01-ingest-stock-quotes.ts index a37694e..ce6c75b 100644 --- a/01-ingest-stock-quotes.ts +++ b/01-ingest-stock-quotes.ts @@ -10,8 +10,8 @@ const env = new Env(); const POLYGON_API_KEY = env.require("POLYGON_API_KEY"); const CONCURRENCY = Number.parseInt(env.get("CONCURRENCY", "6")); const STOCK_QUOTES_TABLE = env.get("STOCK_QUOTES_TABLE", "stock_aggregates"); -const START_DATE = env.get("START_DATE", "2020-01-01"); -const END_DATE = env.get("END_DATE", "2022-03-01"); +const START_DATE = env.get("START_DATE", "2022-03-01"); +const END_DATE = env.get("END_DATE", "2025-01-31"); const polygon = restClient(POLYGON_API_KEY, "https://api.polygon.io", { pagination: true, @@ -65,7 +65,7 @@ for (const date of dateRange(START_DATE, END_DATE)) { ? { symbol: "SPY", ts: new Date(timestamp), - price: high + low / 2, + price: (high + low) / 2, } : { symbol: "", @@ -75,7 +75,11 @@ for (const date of dateRange(START_DATE, END_DATE)) { ), format: "JSONEachRow", }); - // console.log(date, contract.ticker, quotes.results?.length); + + // console.log( + // date, + // quotes.results?.map(({ h: high = 0, l: low = 0 }) => (high + low) / 2) + // ); } console.log("finished", date); } diff --git a/02-fill-stock-quotes.ts b/02-fill-stock-quotes.ts new file mode 100644 index 0000000..c79853a --- /dev/null +++ b/02-fill-stock-quotes.ts @@ -0,0 +1,95 @@ +import { restClient } from "@polygon.io/client-js"; +import { client } from "./clickhouse.js"; +import PQueue from "p-queue"; +import dotenv from "dotenv"; +import { Env } from "@humanwhocodes/env"; + +dotenv.config(); + +const env = new Env(); +const POLYGON_API_KEY = env.require("POLYGON_API_KEY"); +const CONCURRENCY = Number.parseInt(env.get("CONCURRENCY", "6")); +const STOCK_QUOTES_TABLE = env.get("STOCK_QUOTES_TABLE", "stock_aggregates"); +const START_DATE = env.get("START_DATE", "2022-08-01"); +const END_DATE = env.get("END_DATE", "2022-12-31"); + +const polygon = restClient(POLYGON_API_KEY, "https://api.polygon.io", { + pagination: true, +}); + +const queue = new PQueue({ concurrency: CONCURRENCY }); + +function* dateRange( + startDateStr: string, + endDateStr: string +): Generator { + // Convert the start and end date strings to Date objects + const startDate = new Date(startDateStr); + const endDate = new Date(endDateStr); + + // Loop from the start date to the end date + for ( + let currentDate = startDate; + currentDate <= endDate; + currentDate.setDate(currentDate.getDate() + 1) + ) { + // Format the current date as YYYY-MM-DD + const formattedDate = currentDate.toISOString().split("T")[0]; + + // Yield the formatted date + yield formattedDate; + } +} + +for (const date of dateRange(START_DATE, END_DATE)) { + /** To check if the market is open on the given date, we just fetch a few (10, + * for now) rows from the option_quotes table. If there are not 10 rows, then + * the market is closed. */ + const isMarketOpen = + ( + await ( + await client.query({ + query: ` + SELECT * + FROM stock_aggregates + WHERE ts >= '${date} 00:00:00' + AND ts <= '${date} 23:59:59' + LIMIT 10 + `, + format: "JSONEachRow", + }) + ).json() + ).length === 10; + if (isMarketOpen) { + await client.command({ + query: ` + INSERT INTO stock_aggregates_filled + SELECT + symbol, + ts, + price + FROM stock_aggregates + WHERE ts >= '${date} 00:00:00' + AND ts <= '${date} 23:59:59' + ORDER BY symbol, ts + WITH FILL FROM toDateTime('${date} 09:30:00', 'America/New_York') TO toDateTime('${date} 16:15:01', 'America/New_York') INTERPOLATE (price) + `, + }); + } + console.log("finished", date); +} + +// const data = await polygon.options.quotes( +// "O:SPY241220P00600000", +// { +// "timestamp.gte": "2024-12-15", +// "timestamp.lte": "2024-12-16", +// sort: "timestamp", +// order: "asc", +// limit: 50000, +// }, +// { pagination: true } +// ); + +// console.log(data.status); +// console.log(data.results?.length); diff --git a/02-ingest-option-quotes.ts b/03-ingest-option-quotes.ts similarity index 100% rename from 02-ingest-option-quotes.ts rename to 03-ingest-option-quotes.ts diff --git a/03-fill-option-quotes.ts b/04-fill-option-quotes.ts similarity index 100% rename from 03-fill-option-quotes.ts rename to 04-fill-option-quotes.ts diff --git a/04-populate-calendar-stats.ts b/05-populate-calendar-stats.ts similarity index 100% rename from 04-populate-calendar-stats.ts rename to 05-populate-calendar-stats.ts