Skip to content

Commit

Permalink
chore(exchanges): working with binance forward_price logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Romakl committed Feb 29, 2024
1 parent cf1d98c commit e2addba
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 28 deletions.
2 changes: 1 addition & 1 deletion exchanges/constants/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
BINANCE_API_OPTIONS_URL = "https://eapi.binance.com"
BINANCE_API_FUTURES_URL = "https://fapi.binance.com/fapi/v1/premiumIndex"
BINANCE_API_FUTURES_URL = "https://fapi.binance.com"
BINANCE_API_SPOT_URL = "https://api.binance.com"
ByBit_API_URL = "https://api.bybit.com/v2/public/symbols"
OKX_API_URL = "https://www.okex.com/api/spot/v3/instruments"
Expand Down
70 changes: 62 additions & 8 deletions exchanges/fetchers/binance_fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,86 @@ def fetch_options_symbols():

@staticmethod
def fetch_mark_and_underlying_price():
mark_prices = BinanceFetcher.get_response(
mark_prices_options = BinanceFetcher.get_response(
BINANCE_API_OPTIONS_URL + "/eapi/v1/mark"
)
underlying_price = BinanceFetcher.get_response(
BINANCE_API_SPOT_URL + "/api/v3/ticker/price"
)
underlying_price_df = pd.DataFrame(underlying_price)
data_df = pd.DataFrame(mark_prices)
data_df = data_df.loc[data_df["symbol"].str.contains("BTC-")]
mark_prices_options_df = pd.DataFrame(mark_prices_options)
mark_prices_options_df = mark_prices_options_df.loc[
mark_prices_options_df["symbol"].str.contains("BTC-")
]
forward_prices = BinanceFetcher.fetch_mark_price_futures()

# Ensure that only the BTCUSDT price is fetched to match "BTC-" symbols
ud_price = underlying_price_df.loc[
underlying_price_df["symbol"] == "BTCUSDT", "price"
].iloc[0]

data_df["underlying_price"] = float(ud_price)
data_df.rename(columns={"markPrice": "mark_price"}, inplace=True)
mark_prices_options_df["underlying_price"] = float(ud_price)
mark_prices_options_df.rename(columns={"markPrice": "mark_price"}, inplace=True)

# Convert "mark_price" to float
data_df["mark_price"] = data_df["mark_price"].astype(float)
mark_prices_options_df["mark_price"] = mark_prices_options_df[
"mark_price"
].astype(float)
mark_prices_options_df["expiry"] = (
mark_prices_options_df["symbol"].str.split("-").str[1]
)
mark_prices_options_df = mark_prices_options_df.merge(
forward_prices, on="expiry", how="right"
)
# rename symbol_x to symbol
mark_prices_options_df.rename(columns={"symbol_x": "symbol"}, inplace=True)
print(mark_prices_options_df.head())

return data_df[["symbol", "mark_price", "underlying_price"]]
return mark_prices_options_df[
["symbol", "mark_price", "underlying_price", "forward_price"]
]

@staticmethod
def fetch_mark_price_futures():
symbols = BinanceFetcher.fetch_futures_symbols()
mark_prices = [] # This will hold dictionaries
for symbol in symbols:
data = BinanceFetcher.get_response(
BINANCE_API_FUTURES_URL + f"/fapi/v1/depth?symbol={symbol}"
)

bids_df = pd.DataFrame(data["bids"], columns=["price", "quantity"]).astype(
{"price": "float"}
)
asks_df = pd.DataFrame(data["asks"], columns=["price", "quantity"]).astype(
{"price": "float"}
)

# Get maximum bid and minimum ask
best_bid = bids_df["price"].max()
best_ask = asks_df["price"].min()

forward_price = (best_bid + best_ask) / 2
expiry = symbol.split("_")[1]

mark_prices.append(
{
"symbol": symbol,
"best_bid": best_bid,
"best_ask": best_ask,
"forward_price": forward_price,
"expiry": expiry,
}
)

mark_prices_df = pd.DataFrame(mark_prices)
return mark_prices_df

@staticmethod
def fetch_futures_symbols():
data = BinanceFetcher.get_response(BINANCE_API_FUTURES_URL)
data = BinanceFetcher.get_response(
BINANCE_API_FUTURES_URL + "/fapi/v1/premiumIndex"
)
if data:
return [
res.get("symbol") for res in data if "BTCUSDT_" in res.get("symbol", "")
Expand Down
3 changes: 3 additions & 0 deletions exchanges/fetchers/option_fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ def process_okx_data(self, df: pd.DataFrame) -> pd.DataFrame:

def process_binance_data(self, df: pd.DataFrame) -> pd.DataFrame:
prices = self.binance_fetcher.fetch_mark_and_underlying_price()
print(prices)
prices["symbol"] = prices["symbol"].apply(self.transform_symbol_format)

df["symbol"] = df["symbol"].apply(self.convert_usdt_to_usd)
Expand All @@ -174,6 +175,7 @@ def process_binance_data(self, df: pd.DataFrame) -> pd.DataFrame:
)
df["YTM"] = (df["expiry"] - df["datetime"]) / np.timedelta64(1, "Y")
# Merge the prices into the df based on the 'symbol'
print(prices)
df = df.merge(prices, on="symbol", how="left")

df["bid_spread"] = np.maximum(df["mark_price"] - df["bid"], 0)
Expand All @@ -186,6 +188,7 @@ def process_binance_data(self, df: pd.DataFrame) -> pd.DataFrame:
"ask",
"mark_price",
"underlying_price",
"forward_price",
"bid_spread",
"ask_spread",
"datetime",
Expand Down
3 changes: 3 additions & 0 deletions exchanges/handlers/merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ def handle(
self, options_market: List[str], future_market: List[str] | None
) -> pd.DataFrame:
options_data = self.option_market_handler.handle(options_market)
options_data.to_json(
f"{self.exchange}_options_data.json", orient="records", indent=4
)
if future_market:
futures_data = self.future_market_handler.handle(future_market)
merged_data = pd.concat([options_data, futures_data], ignore_index=True)
Expand Down
32 changes: 16 additions & 16 deletions exchanges/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@

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 = pd.DataFrame()
#
# for manager in [binance, deribit, okx]:
# global_orderbook = pd.concat(
# [global_orderbook, manager.load_specific_pairs()], ignore_index=True
# )
# global_orderbook.to_json("global_orderbook.json", orient="records", indent=4)
global_orderbook = pd.read_json("global_orderbook.json")
process = Processing()
x = process.process_global_orderbook(global_orderbook)
x.to_json("global_orderbook_processed.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 = pd.DataFrame()

for manager in [binance]:
global_orderbook = pd.concat(
[global_orderbook, manager.load_specific_pairs()], ignore_index=True
)
global_orderbook.to_json("global_orderbook.json", orient="records", indent=4)
# global_orderbook = pd.read_json("global_orderbook.json")
# process = Processing()
# x = process.process_global_orderbook(global_orderbook)
# x.to_json("global_orderbook_processed.json", orient="records", indent=4)

except Exception as e:
logger.error(f"An unexpected error occurred in the main function: {e}")
Expand Down
6 changes: 3 additions & 3 deletions exchanges/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ def calculate_implied_interest_rates(df):
# Calculate implied interest rates
df = df.copy()

df["rimp"] = (np.log(df["mark_price"]) - np.log(df["underlying_price"])) / df[
"YTM"
]
df["rimp"] = (
np.log(df["forward_price"]) - np.log(df["underlying_price"])
) / df["YTM"]

# Rimp = (ln F − ln S)/T
return df
Expand Down

0 comments on commit e2addba

Please sign in to comment.