Skip to content

Commit

Permalink
Merge pull request #347 from Joewizy/feat/pipeline-dashboard
Browse files Browse the repository at this point in the history
Feat/pipeline dashboard
  • Loading branch information
djeck1432 authored Nov 30, 2024
2 parents 8764daf + 761a0bd commit bea2445
Show file tree
Hide file tree
Showing 14 changed files with 224 additions and 38 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/dashboard_app_pylint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Dashboard App

on: [push]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pylint
- name: Debug Information
run: |
echo "Current directory:"
pwd
echo "\nDirectory structure:"
ls -R
echo "\nGit root directory:"
git rev-parse --show-toplevel
echo "\nSearching for Python files:"
find . -name "*.py"
echo "\nGit ls-files output:"
git ls-files
echo "\nSpecific path search:"
git ls-files 'dashboard_app/*.py'
git ls-files './dashboard_app/*.py'
git ls-files 'apps/dashboard_app/*.py'
git ls-files './apps/dashboard_app/*.py'
- name: Run Pylint
run: |
files=$(git ls-files 'dashboard_app/*.py')
if [ -n "$files" ]; then
pylint $files --disable=all --enable=C0114,C0115,C0116,C0301
fi
4 changes: 4 additions & 0 deletions apps/dashboard_app/charts/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
"""
Imports the Dashboard class from the main module in the dashboard_app.charts package.
"""

from dashboard_app.charts.main import Dashboard
16 changes: 16 additions & 0 deletions apps/dashboard_app/charts/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines the Dashboard class for rendering a DeRisk dashboard using Streamlit.
"""

import streamlit as st

from dashboard_app.charts.main_chart_figure import get_main_chart_figure
Expand All @@ -16,6 +20,9 @@


class Dashboard:
"""
A class representing a dashboard for managing protocol names.
"""
PROTOCOL_NAMES = [
"zkLend",
# "Nostra Alpha",
Expand Down Expand Up @@ -44,6 +51,9 @@ def __init__(self, zklend_state):
self.collateral_token_price = 0

def load_sidebar(self):
"""
Creates an interactive sidebar for selecting multiple protocols, debt and collateral token.
"""
col1, _ = st.columns([1, 3])
with col1:
self.protocols = st.multiselect(
Expand Down Expand Up @@ -73,6 +83,9 @@ def load_sidebar(self):
)

def load_main_chart(self):
"""
Generates a chart that visualizes liquidable debt against available supply.
"""
(
protocol_main_chart_data_mapping,
protocol_loans_data_mapping,
Expand Down Expand Up @@ -116,6 +129,9 @@ def load_main_chart(self):
st.plotly_chart(figure_or_data=figure, use_container_width=True)

def run(self):
"""
This function executes/runs the load_sidebar() and load_main_chart() function.
"""
# Load sidebar with protocol settings
self.load_sidebar()
self.load_main_chart()
39 changes: 33 additions & 6 deletions apps/dashboard_app/charts/main_chart_figure.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
"""
This module includes functions to generate financial charts using token price and liquidity data.
"""

import math

import pandas as pd
import plotly.express
import plotly.graph_objs

from shared.amms import SwapAmm
from shared.state import State
from shared.types import Prices

from dashboard_app.helpers.settings import TOKEN_SETTINGS
from dashboard_app.helpers.tools import (
get_collateral_token_range,
get_custom_data,
get_prices,
get_underlying_address,
)
from shared.amms import SwapAmm
from shared.state import State
from shared.types import Prices

AMMS = ("10kSwap", "MySwap", "SithSwap", "JediSwap")

Expand All @@ -25,6 +30,11 @@ def get_main_chart_data(
collateral_token_underlying_symbol: str,
debt_token_underlying_symbol: str,
) -> pd.DataFrame:
"""
Generates financial chart data based on token prices, liquidity, and debt information.
Takes five parameters and
Returns: A DataFrame containing calculated token prices and liquidable debt data.
"""
collateral_token_underlying_address = get_underlying_address(
token_parameters=state.token_parameters.collateral,
underlying_symbol=collateral_token_underlying_symbol,
Expand Down Expand Up @@ -64,6 +74,10 @@ def get_main_chart_data(
data[f"{amm}_debt_token_supply"] = 0

def compute_supply_at_price(collateral_token_price: float):
"""
Computes the token supply for each AMM at a given collateral token price and
Returns: the token supplied by AMM and total supply across all AMMs.
"""
supplies = {
amm: swap_amms.get_supply_at_price(
collateral_token_underlying_symbol=collateral_token_underlying_symbol,
Expand All @@ -79,7 +93,7 @@ def compute_supply_at_price(collateral_token_price: float):
supplies_and_totals = data["collateral_token_price"].apply(compute_supply_at_price)
for amm in AMMS:
data[f"{amm}_debt_token_supply"] = supplies_and_totals.apply(
lambda x: x[0][amm]
lambda x, amm=amm: x[0][amm]
)
data["debt_token_supply"] = supplies_and_totals.apply(lambda x: x[1])

Expand All @@ -92,6 +106,10 @@ def get_main_chart_figure(
debt_token: str,
collateral_token_price: float,
) -> plotly.graph_objs.Figure:
"""
Generates a plotly figure for the main chart the function takes in four paramters and
Returns: A Plotly figure object for the chart.
"""
color_map_protocol = {
"liquidable_debt_at_interval_zkLend": "#fff7bc", # light yellow
"liquidable_debt_at_interval_Nostra Alpha": "#fec44f", # yellow
Expand Down Expand Up @@ -143,11 +161,12 @@ def get_main_chart_figure(
# Update layout for the stacked bar plot and the separate trace
figure.update_layout(
barmode="stack",
title=f"Liquidable debt and the corresponding supply of {debt_token} at various price intervals of {collateral_token}",
title=f"Liquidable debt and the corresponding supply of {debt_token}"
f" at various price intervals of {collateral_token}",
xaxis_title=f"{collateral_token} Price (USD)",
yaxis_title="Volume (USD)",
legend_title="Legend",
yaxis2=dict(overlaying="y", side="left", matches="y"),
yaxis2={"overlaying": 'y', "side": 'left', "matches": 'y'},
)

# Add the vertical line and shaded region for the current price
Expand Down Expand Up @@ -177,6 +196,10 @@ def get_bar_chart_figures(
) -> tuple[
plotly.graph_objs.Figure, plotly.graph_objs.Figure, plotly.graph_objs.Figure
]:
"""
Generates a bar chart figures for supply, collateral, and debt stats and then
Returns: A tuple of three objects (supply, collateral, and debt charts).
"""
underlying_addresses_to_decimals = {
x.address: int(math.log10(x.decimal_factor)) for x in TOKEN_SETTINGS.values()
}
Expand Down Expand Up @@ -281,6 +304,10 @@ def get_bar_chart_figures(
def get_specific_loan_usd_amounts(
loan: pd.DataFrame,
) -> tuple[pd.DataFrame, pd.DataFrame]:
"""
This function gets the loan amount in usd and then it
Returns: A tuple containing two DataFrames with specific loan USD amounts.
"""
underlying_addresses_to_decimals = {
x.address: int(math.log10(x.decimal_factor)) for x in TOKEN_SETTINGS.values()
}
Expand Down
31 changes: 19 additions & 12 deletions apps/dashboard_app/charts/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This moudel process and transform liquidity, loan, and chart data for protocols.
"""

import logging
import math
from collections import defaultdict
Expand Down Expand Up @@ -77,19 +81,21 @@ def parse_token_amounts(raw_token_amounts: str) -> dict[str, float]:

def create_stablecoin_bundle(data: dict[str, pd.DataFrame]) -> dict[str, pd.DataFrame]:
"""
Creates a stablecoin bundle by merging relevant DataFrames for collateral tokens and debt tokens.
Creates a stablecoin bundle by merging relevant DataFrames for collateral tokens and debt
tokens.
For each collateral token specified in `src.settings.COLLATERAL_TOKENS`, this function finds the
relevant stablecoin pairs from the provided `data` dictionary and merges the corresponding DataFrames
based on the 'collateral_token_price' column. It combines the debt and liquidity data for multiple
stablecoin pairs and adds the result back to the `data` dictionary under a new key.
For each collateral token specified in `src.settings.COLLATERAL_TOKENS`, this function finds
the relevant stablecoin pairs from the provided `data` dictionary and merges the corresponding
Dataframes based on the 'collateral_token_price' column. It combines the debt and liquidity
data for multiple stablecoin pairs and adds the result back to the `data` dictionary under a
new key.
Parameters:
data (dict[str, pandas.DataFrame]): A dictionary where the keys are token pairs and the values are
corresponding DataFrames containing price and supply data.
data (dict[str, pandas.DataFrame]): A dictionary where the keys are token pairs and the values
are corresponding DataFrames containing price and supply data.
Returns:
dict[str, pandas.DataFrame]: The updated dictionary with the newly created stablecoin bundle added.
Returns: dict[str, pandas.DataFrame]:
The updated dictionary with the newly created stablecoin bundle added.
"""

# Iterate over all collateral tokens defined in the settings
Expand All @@ -109,7 +115,7 @@ def create_stablecoin_bundle(data: dict[str, pd.DataFrame]) -> dict[str, pd.Data

if df.empty:
# Log a warning if the DataFrame is empty and skip to the next pair
logging.warning(f"Empty DataFrame for pair: {pair}")
logging.warning("Empty DataFrame for pair: %s", pair)
continue

if combined_df is None:
Expand Down Expand Up @@ -232,10 +238,11 @@ def transform_main_chart_data(
for protocol in protocols:
protocol_main_chart_data = protocol_main_chart_data_mapping[protocol]
if protocol_main_chart_data is None or protocol_main_chart_data.empty:
logging.warning(f"No data for pair {current_pair} from {protocol}")
logging.warning("No data for pair %s from %s", current_pair, protocol)
collateral_token, debt_token = current_pair.split("-")
st.subheader(
f":warning: No liquidable debt for the {collateral_token} collateral token and the {debt_token} debt token exists on the {protocol} protocol."
f":warning: No liquidable debt for the {collateral_token} collateral token and "
f"the {debt_token} debt token exists on the {protocol} protocol."
)
continue

Expand Down
4 changes: 4 additions & 0 deletions apps/dashboard_app/dashboard.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This script loads data and runs the dashboard.
"""

import logging
from dashboard_app.charts import Dashboard
from dashboard_app.helpers.load_data import DashboardDataHandler
Expand Down
7 changes: 7 additions & 0 deletions apps/dashboard_app/data_conector.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This is module connects to a PostgreSQL database and fetches data.
"""

import os

import pandas as pd
Expand All @@ -8,6 +12,9 @@


class DataConnector:
"""
Handles database connection and fetches data.
"""
REQUIRED_VARS = ("DB_USER", "DB_PASSWORD", "DB_HOST", "DB_PORT", "DB_NAME")
ZKLEND_SQL_QUERY = """
SELECT
Expand Down
11 changes: 10 additions & 1 deletion apps/dashboard_app/helpers/ekubo.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
A module that interacts with an API to fetch the latest
liquidity data and applies it to a dataframe.
"""

import logging
import time

Expand All @@ -6,6 +11,10 @@


class EkuboLiquidity:
"""
Fetches data from a liquidity API and send it to the dataframe which updates the
liquidity of a token pair.
"""
URL = "http://178.32.172.153/orderbook/"
DEX = "Ekubo"
LOWER_BOUND_VALUE = 0.95
Expand Down Expand Up @@ -61,7 +70,7 @@ def apply_liquidity_to_dataframe(
data=liquidity,
price=price,
price_diff=price_diff,
bids=True if bids_or_asks["type"] == "bids" else False,
bids = bids_or_asks["type"] == "bids",
),
)
self.data["debt_token_supply"] += self.data["Ekubo_debt_token_supply"]
Expand Down
6 changes: 5 additions & 1 deletion apps/dashboard_app/helpers/load_data.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module loads and handle the data.
"""

import asyncio
import logging
import math
Expand Down Expand Up @@ -69,7 +73,7 @@ def _init_zklend_state(self) -> ZkLendState:
zklend_state.interest_rate_models.debt = zklend_interest_rate_data["debt"].iloc[
0
]
logger.info(f"Initialized ZkLend state in {monotonic() - start:.2f}s")
logger.info("Initialized ZkLend state in %.2fs", monotonic() - start)

return zklend_state

Expand Down
15 changes: 14 additions & 1 deletion apps/dashboard_app/helpers/loans_table.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""
This module organizes and handles the loan data in a tabular manner.
"""

import pandas as pd
from data_handler.handlers.loan_states.nostra_alpha.events import NostraAlphaState
Expand All @@ -8,9 +11,14 @@


def get_protocol(state: State) -> str:
"""
Takes a parameter of State which gets the loan entities and
returns the string.
"""
return state.get_protocol_name



def get_loans_table_data(
state: State,
prices: Prices,
Expand Down Expand Up @@ -41,7 +49,7 @@ def get_loans_table_data(
debt_interest_rate_model=state.interest_rate_models.debt,
prices=prices,
)
if isinstance(state, NostraAlphaState) or isinstance(state, NostraMainnetState):
if isinstance(state, (NostraAlphaState, NostraMainnetState)):
risk_adjusted_debt_usd = loan_entity.compute_debt_usd(
risk_adjusted=True,
debt_token_parameters=state.token_parameters.debt,
Expand Down Expand Up @@ -97,6 +105,11 @@ def get_supply_function_call_parameters(
protocol: str,
token_addresses: list[str],
) -> tuple[list[str], str]:
"""
Takes two parameters of name of protocol and token address and then
Returns a tuple which the first element is the list of token address and
the second is supply function name
"""
if protocol == "zkLend":
return token_addresses, "felt_total_supply"
if protocol in {"Nostra Alpha", "Nostra Mainnet"}:
Expand Down
Loading

0 comments on commit bea2445

Please sign in to comment.