From 8d01768c067b4be4c3c422690aa633291f15c53d Mon Sep 17 00:00:00 2001 From: romakl Date: Thu, 28 Mar 2024 16:22:43 +0200 Subject: [PATCH] fix(exchanges): fixing all mess --- exchanges/exchange_manager.py | 2 +- exchanges/handlers/future.py | 19 ----- .../handlers/future_and_options_handler.py | 37 +++++++++ exchanges/handlers/merge.py | 26 ------- exchanges/handlers/option.py | 27 ------- exchanges/handlers/spot.py | 6 -- exchanges/main.py | 75 +++---------------- exchanges/processing.py | 30 ++++---- 8 files changed, 63 insertions(+), 159 deletions(-) delete mode 100644 exchanges/handlers/future.py create mode 100644 exchanges/handlers/future_and_options_handler.py delete mode 100644 exchanges/handlers/merge.py delete mode 100644 exchanges/handlers/option.py delete mode 100644 exchanges/handlers/spot.py diff --git a/exchanges/exchange_manager.py b/exchanges/exchange_manager.py index 2fe8d97..da5d8c9 100644 --- a/exchanges/exchange_manager.py +++ b/exchanges/exchange_manager.py @@ -8,7 +8,7 @@ from pandas import DataFrame from exchanges.fetchers.binance_fetcher import BinanceFetcher -from exchanges.handlers.merge import MergeMarketHandler +from exchanges.handlers.future_and_options_handler import MergeMarketHandler logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) diff --git a/exchanges/handlers/future.py b/exchanges/handlers/future.py deleted file mode 100644 index 44d7604..0000000 --- a/exchanges/handlers/future.py +++ /dev/null @@ -1,19 +0,0 @@ -import logging -from typing import List -import pandas as pd - -from exchanges.fetchers.future_fetcher import FutureFetcher - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - - -class FutureMarketHandler: - def __init__(self, exchange: str, market_types: List[str]): - self.exchange = exchange - self.market_types = market_types - self.data_fetcher = FutureFetcher(exchange) - - def handle(self) -> pd.DataFrame: - future_symbols = self.data_fetcher.fetch_future_market_symbols("BTC") - return self.data_fetcher.fetch_all_implied_interest_rates(future_symbols) diff --git a/exchanges/handlers/future_and_options_handler.py b/exchanges/handlers/future_and_options_handler.py new file mode 100644 index 0000000..6773e92 --- /dev/null +++ b/exchanges/handlers/future_and_options_handler.py @@ -0,0 +1,37 @@ +from typing import List + +import pandas as pd + +from exchanges.fetchers.future_fetcher import FutureFetcher +from exchanges.fetchers.option_fetcher import OptionFetcher +from exchanges.processing import Processing + + +class MergeMarketHandler: + def __init__(self, exchange, market_types): + self.exchange = exchange + self.future_data_fetcher = FutureFetcher(exchange) + self.options_data_fetcher = OptionFetcher(exchange) + self.market_types = market_types + self.processing = Processing() + + + """ + Fetches the options and future market data for the given exchange and market types (e.g. "BTC"). + """ + def handle( + self, options_market: List[str] + ) -> tuple[pd.DataFrame, pd.DataFrame]: + options_data = self.options_data_fetcher.fetch_market_data( + options_market, str(self.exchange) + ) + options_data = self.processing.eliminate_invalid_quotes(options_data) + + """ + First, we fetch the future market symbols for the given exchange and market types (e.g. "BTC"). + Then, we fetch all the implied interest rates for the future market symbols. + """ + futures_symbols = self.future_data_fetcher.fetch_future_market_symbols("BTC") + future_data = self.future_data_fetcher.fetch_all_implied_interest_rates(futures_symbols) + + return options_data, future_data diff --git a/exchanges/handlers/merge.py b/exchanges/handlers/merge.py deleted file mode 100644 index 3678aca..0000000 --- a/exchanges/handlers/merge.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import List - -import pandas as pd -import json - -from exchanges.handlers.future import FutureMarketHandler -from exchanges.handlers.option import OptionMarketHandler -from exchanges.processing import Processing - - -class MergeMarketHandler: - def __init__(self, exchange, market_types): - self.exchange = exchange - self.market_types = market_types - self.option_market_handler = OptionMarketHandler(exchange, market_types) - self.future_market_handler = FutureMarketHandler(exchange, market_types) - self.processing = Processing() - - def handle( - self, options_market: List[str], future_market: List[str] | None - ) -> tuple[pd.DataFrame, pd.DataFrame]: - options_data = self.option_market_handler.handle(options_market) - options_data = self.processing.eliminate_invalid_quotes(options_data) - future_data = self.future_market_handler.handle() - - return options_data, future_data diff --git a/exchanges/handlers/option.py b/exchanges/handlers/option.py deleted file mode 100644 index a035701..0000000 --- a/exchanges/handlers/option.py +++ /dev/null @@ -1,27 +0,0 @@ -import logging - -from typing import List - -import pandas as pd - -from exchanges.fetchers.option_fetcher import OptionFetcher - -from exchanges.processing import Processing - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - - -class OptionMarketHandler: - def __init__(self, exchange, market_types): - self.exchange = exchange - self.market_types = market_types - self.data_fetcher = OptionFetcher(exchange) - self.processing = Processing() - - def handle(self, market_symbols: List[str]) -> pd.DataFrame: - market_data = self.data_fetcher.fetch_market_data( - market_symbols, str(self.exchange) - ) - - return market_data diff --git a/exchanges/handlers/spot.py b/exchanges/handlers/spot.py deleted file mode 100644 index 6d1b91d..0000000 --- a/exchanges/handlers/spot.py +++ /dev/null @@ -1,6 +0,0 @@ -from typing import Dict, Any - - -class SpotMarketHandler: - def handle(self, symbol: str, market: Dict[str, Any]) -> None: - return None diff --git a/exchanges/main.py b/exchanges/main.py index 0f9b74c..e9e097f 100644 --- a/exchanges/main.py +++ b/exchanges/main.py @@ -15,69 +15,18 @@ def main(): try: - # deribit = DeribitManager(pairs_to_load=["BTC/USD:BTC"], market_types=["option"]) - # binance = BinanceManager( - # pairs_to_load=["BTC/USD:BTC"], market_types=["option", "future"] - # ) - # okx = OKXManager(pairs_to_load=["BTC/USD:BTC"], market_types=["option"]) - # global_orderbook_options = pd.DataFrame() - # global_orderbook_futures = pd.DataFrame() - # - # - # for manager in [binance, deribit]: - # options, futures = manager.load_specific_pairs() - # global_orderbook_options = pd.concat([global_orderbook_options, options]).reset_index(drop=True) - # global_orderbook_futures = pd.concat([global_orderbook_futures, futures]).reset_index(drop=True) - # - # consolidated_options = Processing().consolidate_quotes(global_orderbook_options) - # - # global_orderbook_futures.to_json("futures.json", orient="records", indent=4) - # - # process_quotes = Processing().process_quotes(consolidated_options) - # process_quotes.to_json("quotes.json", orient="records", indent=4) - # process_quotes.to_csv("quotes.csv", index=False) - process_quotes = pd.read_json("quotes.json") - futures = pd.read_json("futures.json") - filter_near_next_term_options = Processing().filter_near_next_term_options( - process_quotes - ) - near_term_options, next_term_options = filter_near_next_term_options - near_term_options.to_json("near_term_options.json", orient="records", indent=4) - next_term_options.to_json("next_term_options.json", orient="records", indent=4) - near_term_implied_forward_price = Processing().calculate_implied_forward_price( - near_term_options - ) - otm_final = Processing().filter_and_sort_options( - near_term_options, near_term_implied_forward_price - ) - - otm_final.to_csv("otm_final.csv", index=False) - - find_missing_expiries_near_term = Processing().find_missing_expiries( - otm_final, futures - ) - interpolate_implied_interest_rates_near_term = ( - Processing().interpolate_implied_interest_rates( - futures, find_missing_expiries_near_term - ) - ) - calculate_wij = Processing().calculate_wij( - otm_final, interpolate_implied_interest_rates_near_term - ) - calculate_sigma_it_squared = Processing().calculate_sigma_it_squared( - calculate_wij, otm_final - ) - calculate_sigma_it_squared.to_csv("sigma_near_squared.csv", index=False) - calculate_wij.to_csv("calculate_wij.csv", index=False) - - interpolate_implied_interest_rates_near_term.to_csv( - "interpolate_implied_interest_rates_near_term.csv", index=False - ) - interpolate_implied_interest_rates_near_term.to_json( - "interpolate_implied_interest_rates_near_term.json", - orient="records", - indent=4, - ) + deribit = DeribitManager(pairs_to_load=["BTC/USD:BTC"], market_types=["option"]) + binance = BinanceManager( + pairs_to_load=["BTC/USD:BTC"], market_types=["option", "future"] + ) + okx = OKXManager(pairs_to_load=["BTC/USD:BTC"], market_types=["option"]) + global_orderbook_options = pd.DataFrame() + global_orderbook_futures = pd.DataFrame() + + for manager in [binance, deribit]: + options, futures = manager.load_specific_pairs() + global_orderbook_options = pd.concat([global_orderbook_options, options]).reset_index(drop=True) + global_orderbook_futures = pd.concat([global_orderbook_futures, futures]).reset_index(drop=True) except Exception as e: logger.error(f"An unexpected error occurred in the main function: {e}") diff --git a/exchanges/processing.py b/exchanges/processing.py index 2d830bb..7d92998 100644 --- a/exchanges/processing.py +++ b/exchanges/processing.py @@ -146,44 +146,40 @@ def filter_and_sort_options(df, Fimp): @staticmethod def calculate_wij(strike_prices_df, interest_rates_df): interest_rates_df["expiry"] = pd.to_datetime(interest_rates_df["expiry"]) + strike_prices_df["expiry"] = pd.to_datetime(strike_prices_df["expiry"]) strike_prices_df.sort_values(by=["expiry", "strike"], inplace=True) merged_df = strike_prices_df.merge( interest_rates_df, on="expiry", how="left", suffixes=("_x", "_y") ) + merged_df["K_prev"] = merged_df["strike"].shift(1) merged_df["K_next"] = merged_df["strike"].shift(-1) merged_df["Delta_K"] = (merged_df["K_next"] - merged_df["K_prev"]) / 2 - merged_df["Delta_K"].fillna(method="bfill", inplace=True) merged_df["Delta_K"].fillna(method="ffill", inplace=True) + merged_df["w_ij"] = ( np.exp(merged_df["implied_interest_rate"] * merged_df["years_to_expiry"]) * merged_df["Delta_K"] ) / (merged_df["strike"] ** 2) - - return merged_df[["expiry", "strike", "w_ij"]] + return merged_df @staticmethod - def calculate_sigma_it_squared(w_ij_df, option_prices_df): - option_prices_df["expiry"] = pd.to_datetime(option_prices_df["expiry"]) - option_prices_df.sort_values(by=["expiry", "strike"], inplace=True) - option_prices_df.to_csv("option_prices.csv", index=False) - - merged_df = w_ij_df.merge( - option_prices_df, on=["expiry", "strike"], how="left", suffixes=("_x", "_y") - ) - - merged_df["sigma_it_squared"] = (1 / merged_df["years_to_expiry"]) * ( - 0.5 * (merged_df["w_ij"] * merged_df["mid_price"]).sum() - - (merged_df["Fimp"] / merged_df["KATM"] - 1) ** 2 + def calculate_sigma_it_squared_for_all(w_ij_df): + T_i = w_ij_df['years_to_expiry'].mean() + F_i = w_ij_df['Fimp'].mean() + K_i_ATM = w_ij_df['KATM'].mean() + + sigma_squared = (1 / T_i) * ( + np.sum(0.5 * w_ij_df['w_ij'] * w_ij_df['mid_price']) - + ((F_i / K_i_ATM) - 1) ** 2 * len(w_ij_df) ) - return merged_df[["expiry", "strike", "sigma_it_squared"]] - + return sigma_squared @staticmethod def find_missing_expiries(options_df, futures_df): options_expiries = options_df["expiry"].unique()