Decentralized finance (#773)

* Add separate view for finbrain for crypto curreny sentiment analysis

* Move json with symbols to separate directory, little refactoring, update readme

* Add screenshot of finbrain for PolkaDot

* Add views for llama, defipulse

* Add llama view with tvl chart

* Add defipulse view

* Add defi controller and move all defi views into defi module

* Add defi controller to main controller

* Add newsletters related to defi

* Add defi docs
This commit is contained in:
jp
2021-10-03 23:26:59 +02:00
committed by GitHub
parent 0b0cf88a56
commit 44fb157ddc
20 changed files with 1341 additions and 3 deletions

View File

@@ -17,6 +17,7 @@ from gamestonk_terminal.helper_funcs import (
from gamestonk_terminal.menu import session
from gamestonk_terminal.cryptocurrency.technical_analysis import ta_controller
from gamestonk_terminal.cryptocurrency.overview import overview_controller
from gamestonk_terminal.cryptocurrency.defi import defi_controller
from gamestonk_terminal.cryptocurrency.due_diligence import (
dd_controller,
coinpaprika_view,
@@ -60,7 +61,7 @@ class CryptoController:
"find",
]
CHOICES_MENUS = ["ta", "dd", "ov", "disc", "report", "onchain"]
CHOICES_MENUS = ["ta", "dd", "ov", "disc", "report", "onchain", "defi"]
SOURCES = {
"bin": "Binance",
@@ -121,6 +122,7 @@ Note: Some of CoinGecko commands can fail. Team is working on fix.
> dd due-diligence for loaded coin, e.g.: coin information, social media, market stats
> ta technical analysis for loaded coin, e.g.: ema, macd, rsi, adx, bbands, obv
> onchain information on different blockchains, e.g.: eth gas fees
> defi decentralized finance information, e.g.: dpi, llama, tvl, lending, borrow, funding
> report generate automatic report
"""
print(help_text)
@@ -664,6 +666,14 @@ Note: Some of CoinGecko commands can fail. Team is working on fix.
else:
return True
def call_defi(self, _):
"""Process defi command"""
defi = defi_controller.menu()
if defi is False:
self.print_help()
else:
return True
def call_finbrain(self, other_args):
"""Process finbrain command"""
parser = argparse.ArgumentParser(

View File

@@ -0,0 +1,537 @@
"""Defi Controller Module"""
__docformat__ = "numpy"
import os
import argparse
from typing import List
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.menu import session
from gamestonk_terminal.helper_funcs import (
get_flair,
parse_known_args_and_warn,
check_positive,
)
from gamestonk_terminal.cryptocurrency.defi import (
defirate_view,
defipulse_view,
llama_view,
substack_view,
)
# pylint: disable=R1732
class DefiController:
"""Defi Controller class"""
CHOICES = [
"cls",
"?",
"help",
"q",
"quit",
]
CHOICES_COMMANDS = [
"dpi",
"funding",
"lending",
"tvl",
"borrow",
"llama",
"newsletter",
]
CHOICES += CHOICES_COMMANDS
def __init__(self):
"""Constructor"""
self.defi_parser = argparse.ArgumentParser(add_help=False, prog="defi")
self.defi_parser.add_argument(
"cmd",
choices=self.CHOICES,
)
def switch(self, an_input: str):
"""Process and dispatch input
Parameters
-------
an_input : str
string with input arguments
Returns
-------
True, False or None
False - quit the menu
True - quit the program
None - continue in the menu
"""
# Empty command
if not an_input:
print("")
return None
(known_args, other_args) = self.defi_parser.parse_known_args(an_input.split())
# Help menu again
if known_args.cmd == "?":
print_help()
return None
# Clear screen
if known_args.cmd == "cls":
os.system("cls||clear")
return None
return getattr(
self, "call_" + known_args.cmd, lambda: "Command not recognized!"
)(other_args)
def call_help(self, *_):
"""Process Help command"""
print_help()
def call_q(self, _):
"""Process Q command - quit the menu"""
return False
def call_quit(self, _):
"""Process Quit command - quit the program"""
return True
def call_dpi(self, other_args: List[str]):
"""Process dpi command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="dpi",
description="""
Displays DeFi Pulse crypto protocols.
[Source: https://defipulse.com/]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=15,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: Rank",
default="Rank",
choices=["Rank", "Name", "Chain", "Category", "TVL", "Change_1D"],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=True,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
defipulse_view.display_defipulse(
top=ns_parser.top,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_llama(self, other_args: List[str]):
"""Process llama command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="llama",
description="""
Display information about listed DeFi Protocols on DeFi Llama.
[Source: https://docs.llama.fi/api]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"-s",
"--sort",
dest="sortby",
type=str,
help="Sort by given column. Default: tvl",
default="tvl",
choices=[
"tvl",
"symbol",
"category",
"chains",
"change_1h",
"change_1d",
"change_7d",
"tvl",
],
)
parser.add_argument(
"--descend",
action="store_false",
help="Flag to sort in descending order (lowest first)",
dest="descend",
default=False,
)
parser.add_argument(
"--desc",
action="store_false",
help="Flag to display description of protocol",
dest="description",
default=False,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
llama_view.display_defi_protocols(
top=ns_parser.top,
sortby=ns_parser.sortby,
descend=ns_parser.descend,
description=ns_parser.description,
export=ns_parser.export,
)
except Exception as e:
print(e, "\n")
def call_tvl(self, other_args: List[str]):
"""Process tvl command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="tvl",
description="""
Displays historical values of the total sum of TVLs from all listed protocols.
[Source: https://docs.llama.fi/api]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
llama_view.display_defi_tvl(top=ns_parser.top, export=ns_parser.export)
except Exception as e:
print(e, "\n")
def call_funding(self, other_args: List[str]):
"""Process funding command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="funding",
description="""
Display Funding rates.
[Source: https://defirate.com/]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"--current",
action="store_false",
default=True,
dest="current",
help="Show Current Funding Rates or Last 30 Days Average",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
defirate_view.display_funding_rates(
top=ns_parser.top, current=ns_parser.current, export=ns_parser.export
)
except Exception as e:
print(e, "\n")
def call_borrow(self, other_args: List[str]):
"""Process borrow command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="borrow",
description="""
Display DeFi borrow rates.
[Source: https://defirate.com/]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"--current",
action="store_false",
default=True,
dest="current",
help="Show Current Borrow Rates or Last 30 Days Average",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
defirate_view.display_borrow_rates(
top=ns_parser.top, current=ns_parser.current, export=ns_parser.export
)
except Exception as e:
print(e, "\n")
def call_lending(self, other_args: List[str]):
"""Process lending command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="lending",
description="""
Display DeFi lending rates.
[Source: https://defirate.com/]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=15,
)
parser.add_argument(
"--current",
action="store_false",
default=True,
dest="current",
help="Show Current Lending Rates or Last 30 Days Average",
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
defirate_view.dislpay_lending_rates(
top=ns_parser.top, current=ns_parser.current, export=ns_parser.export
)
except Exception as e:
print(e, "\n")
def call_newsletter(self, other_args: List[str]):
"""Process newsletter command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="newsletter",
description="""
Display DeFi related substack newsletters.
[Source: substack.com]
""",
)
parser.add_argument(
"-t",
"--top",
dest="top",
type=check_positive,
help="top N number records",
default=10,
)
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
type=str,
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
substack_view.display_newsletters(
top=ns_parser.top, export=ns_parser.export
)
except Exception as e:
print(e, "\n")
def print_help():
"""Print help"""
print("\nDecentralized Finance:")
print(" cls clear screen")
print(" ?/help show this menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print("")
print(" llama DeFi protocols listed on DeFi Llama")
print(" tvl Total value locked of DeFi protocols")
print(" newsletter Recent DeFi related newsletters")
print(" dpi DeFi protocols listed on DefiPulse")
print(" funding Funding reates - current or last 30 days average")
print(" borrow DeFi borrow rates - current or last 30 days average")
print(" lending DeFi ending rates - current or last 30 days average")
print("")
def menu():
"""Defi Menu"""
defi_controller = DefiController()
defi_controller.call_help(None)
while True:
# Get input command from user
if session and gtff.USE_PROMPT_TOOLKIT:
completer = NestedCompleter.from_nested_dict(
{c: None for c in defi_controller.CHOICES}
)
an_input = session.prompt(
f"{get_flair()} (crypto)>(defi)> ",
completer=completer,
)
else:
an_input = input(f"{get_flair()} (crypto)>(defi)> ")
try:
process_input = defi_controller.switch(an_input)
except SystemExit:
print("The command selected doesn't exist\n")
continue
if process_input is False:
return False
if process_input is True:
return True

View File

@@ -0,0 +1,50 @@
"""DeFi Pulse model"""
__docformat__ = "numpy"
import requests
from bs4 import BeautifulSoup
import pandas as pd
def get_defipulse_index() -> pd.DataFrame:
"""Scrapes data from DeFi Pulse with all DeFi Pulse crypto protocols.
[Source: https://defipulse.com/]
Returns
-------
pd.DataFrame
List of DeFi Pulse protocols.
"""
req = requests.get("https://defipulse.com/")
result = req.content.decode("utf8")
soup = BeautifulSoup(result, features="lxml")
table = soup.find("tbody").find_all("tr")
list_of_records = []
for row in table:
row_elements = []
for element in row.find_all("td"):
text = element.text
row_elements.append(text)
list_of_records.append(row_elements)
df = pd.DataFrame(
list_of_records,
columns=[
"x",
"Rank",
"Name",
"Chain",
"Category",
"TVL",
"Change_1D",
],
)
try:
df["Rank"] = df["Rank"].apply(lambda x: int(x.replace(".", "")))
except Exception as e:
print(e, "\n")
df.drop("x", axis=1, inplace=True)
return df

View File

@@ -0,0 +1,51 @@
"""DeFi Pulse view"""
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.cryptocurrency.defi import defipulse_model
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal import feature_flags as gtff
def display_defipulse(top: int, sortby: str, descend: bool, export: str = "") -> None:
"""Displays all DeFi Pulse crypto protocols.
[Source: https://defipulse.com/]
Parameters
----------
top: int
Number of records to display
sortby: str
Key by which to sort data
descend: bool
Flag to sort data descending
export : str
Export dataframe data to csv,json,xlsx file
"""
df = defipulse_model.get_defipulse_index()
df_data = df.copy()
df = df.sort_values(by=sortby, ascending=descend)
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"dpi",
df_data,
)

View File

@@ -0,0 +1,122 @@
"""DeFi Rate model"""
__docformat__ = "numpy"
import requests
from bs4 import BeautifulSoup
from bs4.element import Tag
import pandas as pd
def _scrape_defirate(url: str, current: bool = True) -> Tag:
"""Helper method that scrapes table object from defirate.com
[Source: https://defirate.com/]
Parameters
----------
url: str
Defirate url
current: bool
Flag that indicates if you want to scrape current data or last 30 days average.
Returns
-------
bs4.element.Tag
Table with scraped data
"""
current_or_average_map = {
True: "table-container",
False: "table-container table-hidden",
}
div_class = current_or_average_map[current]
req = requests.get(url)
soup = BeautifulSoup(req.text, features="lxml")
table = soup.find("div", class_=div_class).find("table")
return table
def get_funding_rates(current: bool = True) -> pd.DataFrame:
"""Funding rates are transfer payments made between long and short positions on perpetual swap futures markets.
They’re designed to keep contract prices consistent with the underlying asset.
[Source: https://defirate.com/]
Parameters
----------
current: bool
If true displays current funding rate values. If false displays last 30 day average of funding rates.
-------
pd.DataFrame
Dataframe with funding rates.
"""
url = "https://defirate.com/funding/"
table = _scrape_defirate(url, current)
items = []
first_row = table.find("thead").text.strip().split()
headers = [r for r in first_row if r != "Trade"]
headers.insert(0, "Symbol")
for i in table.find_all("td"):
items.append(i.text.strip())
fundings = [items[i : i + 5] for i in range(0, len(items), 5)]
return pd.DataFrame(columns=headers, data=fundings)
def get_lending_rates(current: bool = True) -> pd.DataFrame:
"""Decentralized Finance lending – or DeFi lending for short – allows users to supply cryptocurrencies
in exchange for earning an annualized return.
[Source: https://defirate.com]
Parameters
----------
current: bool
If true displays current lending rates values. If false displays last 30 day average of lending rates.
Returns
-------
pd.DataFrame
Dataframe with lending rates.
"""
url = "https://defirate.com/loans/?exchange_table_type=lend"
table = _scrape_defirate(url, current)
items = []
first_row = table.find("thead").text.strip().split("\n")
headers = [r for r in first_row if r not in ["Lend", ""]]
headers.insert(0, "Symbol")
for i in table.find_all("td"):
items.append(i.text.strip())
lendings = [items[i : i + 12] for i in range(0, len(items), 12)]
return pd.DataFrame(columns=headers, data=lendings)
def get_borrow_rates(current: bool = True) -> pd.DataFrame:
"""One aspect of Decentralized Finance (DeFi) is the ability to take out a loan on top cryptocurrencies at any time
in an entirely permissionless fashion.By using smart contracts, borrowers are able to lock collateral to protect
against defaults while seamlesslyadding to or closing their loans at any time.
[Source: https://defirate.com]
Parameters
----------
current: bool
If true displays current borrow rates values. If false displays last 30 day average of borrow rates.
Returns
-------
pd.DataFrame
Dataframe with borrow rates
"""
url = "https://defirate.com/loans/?exchange_table_type=borrow"
table = _scrape_defirate(url, current)
items = []
first_row = table.find("thead").text.strip().split("\n")
headers = [r for r in first_row if r not in ["Borrow", ""]]
headers.insert(0, "Symbol")
for i in table.find_all("td"):
items.append(i.text.strip())
borrowings = [items[i : i + 12] for i in range(0, len(items), 12)]
return pd.DataFrame(columns=headers, data=borrowings)

View File

@@ -0,0 +1,129 @@
"""DeFi Rate View"""
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal.cryptocurrency.defi import defirate_model
from gamestonk_terminal import feature_flags as gtff
def display_funding_rates(top: int, current: bool = True, export: str = "") -> None:
"""Display Funding rates - transfer payments made between long and short positions on perpetual swap futures markets
[Source: https://defirate.com/]
Parameters
----------
top: int
Number of records to display
current: bool
If true displays current funding rate values. If false displays last 30 day average of funding rates.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = defirate_model.get_funding_rates(current)
df_data = df.copy()
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"funding",
df_data,
)
def dislpay_lending_rates(top: int, current: bool = True, export: str = "") -> None:
"""Displays top DeFi lendings. Decentralized Finance lending – allows users to supply cryptocurrencies
in exchange for earning an annualized return
[Source: https://defirate.com/]
Parameters
----------
top: int
Number of records to display
current: bool
If true displays current funding rate values. If false displays last 30 day average of funding rates.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = defirate_model.get_lending_rates(current)
df_data = df.copy()
df = df.loc[:, ~df.eq("–").all()]
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"lending",
df_data,
)
def display_borrow_rates(top: int, current: bool = True, export: str = "") -> None:
"""Displays DeFi borrow rates. By using smart contracts, borrowers are able to lock collateral
to protect against defaults while seamlessly adding to or closing their loans at any time.
[Source: https://defirate.com/]
Parameters
----------
top: int
Number of records to display
current: bool
If true displays current funding rate values. If false displays last 30 day average of funding rates.
export : str
Export dataframe data to csv,json,xlsx file
"""
df = defirate_model.get_borrow_rates(current)
df_data = df.copy()
df = df.loc[:, ~df.eq("–").all()]
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"borrow",
df_data,
)

View File

@@ -0,0 +1,68 @@
"""Llama model"""
__docformat__ = "numpy"
from datetime import datetime
import textwrap
import requests
import pandas as pd
import numpy as np
def get_defi_protocols() -> pd.DataFrame:
"""Returns information about listed DeFi protocols, their current TVL and changes to it in the last hour/day/week.
[Source: https://docs.llama.fi/api]
Returns
-------
pd.DataFrame
Information about DeFi protocols
"""
response = requests.get("https://api.llama.fi/protocols")
columns = [
"name",
"symbol",
"category",
"chains",
"change_1h",
"change_1d",
"change_7d",
"tvl",
"url",
"description",
]
if response.status_code != 200:
raise Exception(f"Status code: {response.status_code}. Resason {response.text}")
try:
df = pd.DataFrame(response.json())
df.replace({float(np.nan): None}, inplace=True)
df["chains"] = df["chains"].apply(
lambda x: "\n".join(textwrap.wrap(", ".join(x), width=50))
)
df["description"] = df["description"].apply(
lambda x: "\n".join(textwrap.wrap(x, width=70)) if isinstance(x, str) else x
)
return df[columns]
except Exception as e:
raise ValueError("Wrong response type\n") from e
def get_defi_tvl() -> pd.DataFrame:
"""Returns historical values of the total sum of TVLs from all listed protocols.
[Source: https://docs.llama.fi/api]
Returns
-------
pd.DataFrame
Historical values of total sum of Total Value Locked from all listed protocols.
"""
response = requests.get("https://api.llama.fi/charts")
if response.status_code != 200:
raise Exception(f"Status code: {response.status_code}. Resason {response.text}")
try:
df = pd.DataFrame(response.json())
df["date"] = df["date"].apply(lambda x: datetime.fromtimestamp(int(x)).date())
return df
except Exception as e:
raise ValueError("Wrong response data") from e

View File

@@ -0,0 +1,116 @@
"""Llama View"""
__docformat__ = "numpy"
import os
from tabulate import tabulate
import matplotlib.pyplot as plt
from gamestonk_terminal.cryptocurrency.defi import llama_model
from gamestonk_terminal.helper_funcs import (
export_data,
plot_autoscale,
long_number_format,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.config_plot import PLOT_DPI
def display_defi_protocols(
top: int, sortby: str, descend: bool, description: bool, export: str = ""
) -> None:
"""Display information about listed DeFi protocols, their current TVL and changes to it in the last hour/day/week.
[Source: https://docs.llama.fi/api]
Parameters
----------
top: int
Number of records to display
sortby: str
Key by which to sort data
descend: bool
Flag to sort data descending
description: bool
Flag to display description of protocol
export : str
Export dataframe data to csv,json,xlsx file
"""
df = llama_model.get_defi_protocols()
df_data = df.copy()
df = df.sort_values(by=sortby, ascending=descend)
df["tvl"] = df["tvl"].apply(lambda x: long_number_format(x))
if not description:
df.drop(["description", "url"], axis=1, inplace=True)
else:
df = df[
[
"name",
"symbol",
"category",
"description",
"url",
]
]
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".2f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"llama",
df_data,
)
def display_defi_tvl(top: int, export: str = "") -> None:
"""Displays historical values of the total sum of TVLs from all listed protocols.
[Source: https://docs.llama.fi/api]
Parameters
----------
top: int
Number of records to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df = llama_model.get_defi_tvl()
df_data = df.copy()
df = df.tail(top)
df["totalLiquidityUSD"] = df["totalLiquidityUSD"] / 1_000_000_000
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
plt.plot(df["date"], df["totalLiquidityUSD"], "-ok", ms=2)
plt.xlabel("Time")
plt.xlim(df["date"].iloc[0], df["date"].iloc[-1])
plt.gcf().autofmt_xdate()
plt.ylabel("Total Value Locked USD [1B]")
plt.grid(b=True, which="major", color="#666666", linestyle="-")
plt.minorticks_on()
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
plt.title("Total Value Locked in DeFi [Billions USD]")
plt.show()
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"tvl",
df_data,
)

View File

@@ -0,0 +1,86 @@
"""Substack model"""
__docformat__ = "numpy"
import textwrap
import concurrent.futures
import pandas as pd
import requests
from bs4 import BeautifulSoup
from dateutil import parser
def scrape_substack(url: str) -> list:
"""Helper method to scrape newsletters from substack.
[Source: substack.com]
Parameters
----------
url: str
Url to newsletter on substack domain.
Returns
-------
list
list of news from given newsletter
"""
req = requests.get(url)
soup = BeautifulSoup(req.text, features="lxml")
results = []
posts = soup.find("div", class_="portable-archive-list").find_all(
"div", class_="post-preview portable-archive-post has-image has-author-line"
)
for post in posts:
title, url, time = (
post.a.text,
post.a["href"],
post.find("time").get("datetime"),
)
results.append([title, url, time])
return results
def get_newsletters() -> pd.DataFrame:
"""Scrape all substack newsletters from url list.
[Source: substack.com]
Returns
-------
pd.DataFrame
DataFrame with recent news from most popular DeFi related newsletters.
"""
urls = [
"https://defiweekly.substack.com/archive",
"https://newsletter.thedefiant.io/archive",
"https://thedailygwei.substack.com/archive",
"https://todayindefi.substack.com/archive",
"https://newsletter.banklesshq.com/archive",
"https://defislate.substack.com/archive",
]
threads = len(urls)
newsletters = []
with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor:
for newsletter in executor.map(scrape_substack, urls):
try:
newsletters.append(pd.DataFrame(newsletter))
except KeyError as e:
print(e, "\n")
continue
df = pd.concat(newsletters, ignore_index=True)
df.columns = ["Title", "Link", "Date"]
df["Title"] = df["Title"].apply(lambda x: "".join(i for i in x if ord(i) < 128))
df["Date"] = df["Date"].apply(
lambda x: parser.parse(x).strftime("%Y-%m-%d %H:%M:%S")
)
df["Title"] = df["Title"].apply(
lambda x: "\n".join(textwrap.wrap(x, width=50)) if isinstance(x, str) else x
)
return (
df[["Title", "Date", "Link"]]
.sort_values(by="Date", ascending=False)
.reset_index(drop="index")
)

View File

@@ -0,0 +1,46 @@
"""Substack View"""
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.cryptocurrency.defi import substack_model
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal import feature_flags as gtff
def display_newsletters(top: int = 10, export: str = "") -> None:
"""Display DeFi related substack newsletters.
[Source: substack.com]
Parameters
----------
top: int
Number of records to display
export : str
Export dataframe data to csv,json,xlsx file
"""
df = substack_model.get_newsletters()
df_data = df.copy()
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(top),
headers=df.columns,
floatfmt=".0f",
showindex=False,
tablefmt="fancy_grid",
),
"\n",
)
else:
print(df.to_string, "\n")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"newsletter",
df_data,
)

View File

@@ -63,8 +63,8 @@ def get_whales_transactions(min_value: int = 800000, limit: int = 100) -> pd.Dat
Crypto wales transactions
"""
min_value = 800000 if min_value > 800000 else min_value
limit = 100 if limit > 100 else limit
min_value = max(min_value, 800000)
limit = max(limit, 100)
params = {"limit": limit, "min_value": min_value}

View File

@@ -0,0 +1,5 @@
---
geekdocCollapseSection: true
---
{{< toc-tree >}}

View File

@@ -0,0 +1,16 @@
```
usage: borrow [-t TOP] [--current] [--export {csv,json,xlsx}] [-h]
```
Display DeFi borrow rates. [Source: https://defirate.com/]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
--current Show Current Borrow Rates or Last 30 Days Average
(default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,19 @@
```
usage: dpi [-t TOP] [-s {Rank,Name,Chain,Category,TVL,Change_1D}] [--descend]
[--export {csv,json,xlsx}] [-h]
```
Displays DeFi Pulse crypto protocols. [Source: https://defipulse.com/]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 15)
-s {Rank,Name,Chain,Category,TVL,Change_1D}, --sort {Rank,Name,Chain,Category,TVL,Change_1D}
Sort by given column. Default: Rank (default: Rank)
--descend Flag to sort in descending order (lowest first)
(default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,16 @@
```
usage: funding [-t TOP] [--current] [--export {csv,json,xlsx}] [-h]
```
Display Funding rates. [Source: https://defirate.com/]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
--current Show Current Funding Rates or Last 30 Days Average
(default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,16 @@
```
usage: lending [-t TOP] [--current] [--export {csv,json,xlsx}] [-h]
```
Display DeFi lending rates. [Source: https://defirate.com/]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 15)
--current Show Current Lending Rates or Last 30 Days Average
(default: True)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,21 @@
```
usage: llama [-t TOP]
[-s {tvl,symbol,category,chains,change_1h,change_1d,change_7d,tvl}]
[--descend] [--desc] [--export {csv,json,xlsx}] [-h]
```
Display information about listed DeFi Protocols on DeFi Llama. [Source:https://docs.llama.fi/api]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
-s {tvl,symbol,category,chains,change_1h,change_1d,change_7d,tvl}, --sort {tvl,symbol,category,chains,change_1h,change_1d,change_7d,tvl}
Sort by given column. Default: tvl (default: tvl)
--descend Flag to sort in descending order (lowest first)
(default: False)
--desc Flag to display description of protocol (default:
False)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,14 @@
```
usage: newsletter [-t TOP] [--export {csv,json,xlsx}] [-h]
```
Display DeFi related substack newsletters. [Source: substack.com]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```

View File

@@ -0,0 +1,16 @@
```
usage: tvl [-t TOP] [--export {csv,json,xlsx}] [-h]
```
Displays historical values of the total sum of TVLs from all listed protocols.
[Source: https://docs.llama.fi/api]
```
optional arguments:
-t TOP, --top TOP top N number records (default: 10)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default:
)
-h, --help show this help message (default: False)
```