Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PNL & Wallet code cleanups #766

Merged
merged 10 commits into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion elfpy/eth/receipts.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def get_event_object(
event_signature_text = f"{name}({inputs})"
event_signature_hex = web3.keccak(text=event_signature_text).hex()
# Find match between log's event signature and ABI's event signature
receipt_event_signature_hex = log["topics"][0].hex()
receipt_event_signature_hex = log["topics"][0].hex() # first index gives event signature
if event_signature_hex == receipt_event_signature_hex and name is not None:
# Decode matching log
contract_event = contract.events[name]()
Expand Down
8 changes: 6 additions & 2 deletions elfpy/hyperdrive_interface/hyperdrive_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ def fetch_hyperdrive_address_from_url(contracts_url: str) -> HyperdriveAddresses
response = requests.get(contracts_url, timeout=60)
# Check the status code and retry the request if it fails
if response.status_code != 200:
logging.warning("Request failed with status code %s @ %s", response.status_code, time.ctime())
logging.warning(
"Request for contracts_url=%s failed with status code %s @ %s",
contracts_url,
response.status_code,
time.ctime(),
)
time.sleep(10)
continue
# If successful, exit attempt loop
break

if response is None:
raise ConnectionError("Request failed, returning status `None`")
if response.status_code != 200:
Expand Down
81 changes: 81 additions & 0 deletions examples/hackweek_demo/calc_pnl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""Plots the pnl."""
from __future__ import annotations

import logging

import pandas as pd
from extract_data_logs import calculate_spot_price


def calc_total_returns(pool_config: pd.Series, pool_info: pd.DataFrame, current_wallet: pd.DataFrame) -> pd.Series:
"""Calculates the most current pnl values."""
# pylint: disable=too-many-locals
# Most current block timestamp
latest_pool_info = pool_info.loc[pool_info.index.max()]
block_timestamp = latest_pool_info["timestamp"].timestamp()
# Calculate for base
base_balance = current_wallet[current_wallet["baseTokenType"] == "BASE"]["tokenValue"]
# Calculate for lp
wallet_lps = current_wallet[current_wallet["baseTokenType"] == "LP"]
lp_returns = wallet_lps["tokenValue"] * latest_pool_info["sharePrice"]
# Calculate for shorts
wallet_shorts = current_wallet[current_wallet["baseTokenType"] == "SHORT"]
short_spot_prices = calc_full_term_spot_price(
latest_pool_info["shareReserves"],
latest_pool_info["bondReserves"],
pool_config["invTimeStretch"],
pool_config["initialSharePrice"],
pool_config["positionDuration"],
wallet_shorts["maturityTime"],
block_timestamp,
)
shorts_returns = wallet_shorts["tokenValue"] * (1 - short_spot_prices)
# Calculate for longs
wallet_longs = current_wallet[current_wallet["baseTokenType"] == "LONG"]
long_spot_prices = calc_full_term_spot_price(
latest_pool_info["shareReserves"],
latest_pool_info["bondReserves"],
pool_config["invTimeStretch"],
pool_config["initialSharePrice"],
pool_config["positionDuration"],
wallet_longs["maturityTime"],
block_timestamp,
)
long_returns = wallet_longs["tokenValue"] * long_spot_prices
# Calculate for withdrawal shares
wallet_withdrawl = current_wallet[current_wallet["baseTokenType"] == "WITHDRAWL_SHARE"]
withdrawl_returns = wallet_withdrawl["tokenValue"] * latest_pool_info.sharePrice
# Add pnl to current_wallet information
# Index should match, so it's magic
current_wallet.loc[base_balance.index, "pnl"] = base_balance
current_wallet.loc[lp_returns.index, "pnl"] = lp_returns
current_wallet.loc[shorts_returns.index, "pnl"] = shorts_returns
current_wallet.loc[long_returns.index, "pnl"] = long_returns
current_wallet.loc[withdrawl_returns.index, "pnl"] = withdrawl_returns
total_returns = current_wallet.reset_index().groupby("walletAddress")["pnl"].sum()
return total_returns


def calc_full_term_spot_price(
share_reserves,
bond_reserves,
time_stretch,
initial_share_price,
position_duration,
maturity_timestamp,
block_timestamp,
):
"""Calculate the spot price given the pool info data."""
# pylint: disable=too-many-arguments
full_term_spot_price = calculate_spot_price(share_reserves, bond_reserves, initial_share_price, time_stretch)
time_left_seconds = maturity_timestamp - block_timestamp
if isinstance(time_left_seconds, pd.Timedelta):
time_left_seconds = time_left_seconds.total_seconds()
time_left_in_years = time_left_seconds / position_duration
logging.info(
" spot price is weighted average of %s(%s) and 1 (%s)",
full_term_spot_price,
time_left_in_years,
1 - time_left_in_years,
)
return full_term_spot_price * time_left_in_years + 1 * (1 - time_left_in_years)
212 changes: 0 additions & 212 deletions examples/hackweek_demo/plot_pnl.py

This file was deleted.

13 changes: 10 additions & 3 deletions examples/hackweek_demo/run_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import mplfinance as mpf
import pandas as pd
import streamlit as st
from calc_pnl import calc_total_returns
from dotenv import load_dotenv
from extract_data_logs import get_combined_data
from plot_fixed_rate import calc_fixed_rate, plot_fixed_rate
from plot_ohlcv import calc_ohlcv, plot_ohlcv
from plot_pnl import calculate_current_pnl

from elfpy.data import postgres

Expand Down Expand Up @@ -222,8 +222,15 @@ def username_to_address(lookup: pd.DataFrame, selected_list: pd.Series) -> pd.Se
(fixed_rate_x, fixed_rate_y) = calc_fixed_rate(combined_data, config_data)
ohlcv = calc_ohlcv(combined_data, config_data, freq="5T")

curr_pnl = calculate_current_pnl(config_data, pool_info_data, wallets)
comb_rank, ind_rank = get_leaderboard(curr_pnl, user_lookup)
# temporary hack because we know they started with 1e6 base.
current_reutrns = calc_total_returns(config_data, pool_info_data, wallets)
# TODO: FIX PNL CALCULATIONS TO INCLUDE DEPOSITS
# agent PNL is their click trade pnl + bot pnls
# TODO: FIX BOT RESTARTS
# Add initial budget column to bots
# when bot restarts, use initial budget for bot's wallet address to set "budget" in Agent.Wallet

comb_rank, ind_rank = get_leaderboard(current_reutrns, user_lookup)

with ticker_placeholder.container():
st.header("Ticker")
Expand Down