From 6e6f5f78e2ef201f0cc91642cc84c40bce08a045 Mon Sep 17 00:00:00 2001 From: Ashay Parikh Date: Thu, 8 Feb 2024 21:23:36 -0600 Subject: [PATCH] Account for option expiry hours/minutes --- Cargo.toml | 4 ++-- README.md | 13 ++++++++++--- js/parse.js | 26 ++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bb45a01..1d8eb2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" # Comment out if you want benchmark to run/simd_vol importable into other files -[lib] -crate-type = ["cdylib"] +# [lib] +# crate-type = ["cdylib"] [dependencies] wide = "0.7.13" diff --git a/README.md b/README.md index 42c8110..7fcf455 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ A fast, practical Implied Volatility Surface Explorer for SPY and similar option To run locally, first compile from Rust to WASM with (if your machine doesn't support WASM, remove the RUSTFLAGS): +```toml +# Add below to Cargo.toml +[lib] +crate-type = ["cdylib"] +``` + ```sh RUSTFLAGS='-C target-feature=+simd128' wasm-pack build --target web ``` @@ -55,15 +61,16 @@ cargo test Calculated on a Macbook M1: -For ~25000 options: +For ~25000 options (~25x speed-up): -- `bs::implied_vol()` (single): ~23.2ms +- `bs::implied_vol()` (single): ~25.2ms - `vol32x8::implied_vol()` (SIMD and multithreaded): ~1ms # Extensions 1. In real-life applications, the implied volatility calculation should happen in the backend in order to full utilize SIMD instructions and multithreading. Instead of being converted to WASM, the Rust code can be deployed in a backend system and connected to the frontend with HTTP or another protocol. -2. If the Rust web port is kept, multithreading can be utilized in the frontend by enabling `SharedArrayBuffer` in the browser, adding [wasm-bindgen-rayon](https://github.com/RReverser/wasm-bindgen-rayon), and re-compiling to WASM. +2. If the Rust -> WASM is kept, multithreading can be utilized in the frontend by enabling `SharedArrayBuffer` in the browser, adding [wasm-bindgen-rayon](https://github.com/RReverser/wasm-bindgen-rayon), and re-compiling to WASM. +3. Support other historical or realtime market data feeds. # License diff --git a/js/parse.js b/js/parse.js index 7900e42..39d2b9a 100644 --- a/js/parse.js +++ b/js/parse.js @@ -100,9 +100,30 @@ export function parseOptionData(data) { let year_line = split_line[1].split(" "); current_year = parseInt(year_line[1], 10); + const hour_minutes = year_line[3].split(":") + const hour = parseInt(hour_minutes[0], 10); + const minutes = parseInt(hour_minutes[1], 10); + const am_pm = year_line[4]; + + // Assume time is in EST + let date = new Date(); + date.setHours(hour + (am_pm.toLowerCase() === "am" ? 0 : 12)); + date.setMinutes(minutes); + + let optionExpireDate = new Date(); + optionExpireDate.setHours(16); + optionExpireDate.setMinutes(15); + + let difference = (optionExpireDate.getTime() - date.getTime()) / 86400000; let current_day = parseInt(removeNonNumCharacters(date_line[2])); - today = getDaysFromJanuary(month) + current_day; + if (difference < 0) { + // Assume 1 day difference if we're past the end of day for the option + difference = 1; + } + + // Subtract to account for the hour difference since options expire at 4:15 PM + today = getDaysFromJanuary(month) + current_day - difference; } else if (line_counter >= 4) { let split_line = line.split(","); @@ -130,8 +151,9 @@ export function parseOptionData(data) { let days = parseFloat(date_price[2]); let month_days = getDaysFromJanuary(date_price[1]); + // Add one for end of day - let expiration = ((year - current_year)) * 365.0 + month_days + days + 1.0; + let expiration = ((year - current_year)) * 365.0 + month_days + days; years_to_expiry.push((expiration - today) / 365.0);