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.
calendar-optimizer-deno/src/ingest-options-from-polygon...

130 lines
4.4 KiB
JavaScript

//import { restClient as PolygonClient } from '@polygon.io/client-js';
import { createClient as createClickhouseClient } from '@clickhouse/client'
import { sleep, getPolygonApiKey } from './util.mjs';
//const polygonClient = PolygonClient(apiKey, "https://api.polygon.io", {pagination: false, trace: true,}); // automatically call `next_url` if there is one
const clickhouse = createClickhouseClient({username:'avraham', password:'buginoo'});
const optionContractsTableName = "option_aggregates";
async function deleteClickhouseTable(){
await clickhouse.command({
query: `DROP TABLE IF EXISTS ${optionContractsTableName}`,
})
}
async function createClickhouseTable(){
await clickhouse.command({
query: `
CREATE TABLE ${optionContractsTableName}
(
symbol LowCardinality(String),
asOfDate Date,
expirationDate Date,
optionType Enum('call', 'put'),
strike Decimal64(9)
)
ENGINE MergeTree()
ORDER BY (symbol, asOfDate, expirationDate, optionType, strike)
`,
});
/*
await clickhouse.command({
query: `
CREATE TABLE ${optionAggregatesTableName}
(
symbol LowCardinality(String),
tsStart DateTime32,
expirationDate DateTime32,
optionType Enum('call', 'put'),
strike Decimal64(9),
open Decimal64(9),
close Decimal64(9),
low Decimal64(9),
high Decimal64(9),
volume UInt64,
volume_weighted_price Decimal64(9)
)
ENGINE MergeTree()
ORDER BY (tsStart, symbol, expirationDate, optionType, strike)
`,
});
*/
}
async function insertResultsIntoClickhouse(symbol, asOfDate, optionContractsResult){
await clickhouse.insert({
table: optionContractsTableName,
// structure should match the desired format, JSONEachRow in this example
values: optionContractsResult.results.map(r=>({
symbol,
asOfDate,
expirationDate: r.expiration_date,
optionType: r.contract_type,
strike: r.strike_price
})),
format: 'JSONEachRow',
});
console.log('inserted', symbol);
}
/**
* Get all available option expirations and strikes, from the point-of-view of a given date
*/
async function fetchAvailableOptionExpirationsAndStrikesAsOfDate(symbol, asOfDate){
const limit = 1000;
let apiKey = await getPolygonApiKey();
let optionContractsResult = await (await fetch(`https://api.polygon.io/v3/reference/options/contracts?underlying_ticker=${symbol}&contract_type=call&as_of=${asOfDate}&expired=false&order=asc&limit=${limit}&sort=expiration_date&apiKey=${apiKey}`)).json();
console.log(optionContractsResult.results.length);
if(optionContractsResult.status === 'OK' && typeof optionContractsResult.results !== "undefined" && optionContractsResult.results.length > 0){
await insertResultsIntoClickhouse(symbol, asOfDate, optionContractsResult);
while(optionContractsResult.hasOwnProperty("next_url")){
apiKey = await getPolygonApiKey();
optionContractsResult = await (await fetch(`${optionContractsResult.next_url}&apiKey=${apiKey}`)).json();
if(optionContractsResult.status === 'OK' && typeof optionContractsResult.results !== "undefined" && optionContractsResult.results.length > 0){
console.log(optionContractsResult.results.length);
await insertResultsIntoClickhouse(symbol, asOfDate, optionContractsResult);
}
else{
console.log(optionContractsResult);
}
}
}
else{
console.log(optionContractsResult);
}
}
const stockAggregatesTableName = "stock_aggregates";
async function fetchMarketDates(){
return (await (await clickhouse.query({
query: `SELECT DISTINCT(Date(tsStart)) FROM ${stockAggregatesTableName}`,
format: 'JSONCompactEachRow'
})).json()).map((r)=>r[0]);
}
await deleteClickhouseTable();
await createClickhouseTable();
const marketDates = await fetchMarketDates();
for(let asOfDate of marketDates){
for(let symbol of ["AAPL", "GOOGL", "MSFT", "TSLA", "AMD", "NFLX", "SPY"]){
await fetchAvailableOptionExpirationsAndStrikesAsOfDate(symbol, asOfDate);
}
}
/**
* For each day (not aggregate), look-up the available option contracts (i.e.
* all unique type/strike/exp combinations). Limit is 1000, but it gives you a
* "nextUrl", so keep calling that until all results are in.
*/
/**
* For each aggregate and the contracts on that day, get option aggregates
*/
await clickhouse.close();