From 4d99dabbd8fc063d9493def21fe693c7e92c80ca Mon Sep 17 00:00:00 2001 From: jose-donato Date: Sun, 24 Jul 2022 17:38:02 +0100 Subject: [PATCH 1/3] added funding rate feature to dd menu --- i18n/en.yml | 1 + .../due_diligence/coinglass_model.py | 64 ++++++++++++++++++- .../due_diligence/coinglass_view.py | 41 +++++++++++- .../due_diligence/dd_controller.py | 27 +++++++- .../terminal/crypto/dd/fundrate/_index.md | 11 ++++ .../content/terminal/crypto/dd/oi/_index.md | 2 +- website/data/menu/main.yml | 2 + 7 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 website/content/terminal/crypto/dd/fundrate/_index.md diff --git a/i18n/en.yml b/i18n/en.yml index 2c1c96544fde..926908433c22 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -612,6 +612,7 @@ en: crypto/dd/change: 30d change of supply held on exchange wallets crypto/dd/eb: total balance held on exchanges (in percentage and units) crypto/dd/oi: open interest per exchange + crypto/dd/fundrate: funding rate per exchange crypto/dd/basic: basic information about loaded coin crypto/dd/ps: price and supply related metrics for loaded coin crypto/dd/mkt: all markets for loaded coin diff --git a/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py b/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py index b2dbf60b5dd3..2b6aabeee906 100644 --- a/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py +++ b/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py @@ -16,6 +16,68 @@ INTERVALS = [0, 1, 2, 4] +@log_start_end(log=logger) +def get_funding_rate(symbol: str) -> pd.DataFrame: + """Returns open interest by exchange for a certain symbol + [Source: https://coinglass.github.io/API-Reference/] + + Parameters + ---------- + symbol : str + Crypto Symbol to search open interest futures (e.g., BTC) + + Returns + ------- + pd.DataFrame + funding rate per exchange + """ + + url = api_url + f"futures/funding_rates_chart?symbol={symbol.upper()}&type=C" + + headers = {"coinglassSecret": cfg.API_COINGLASS_KEY} + + response = requests.request("GET", url, headers=headers) + + df = pd.DataFrame() + + if response.status_code == 200: + res_json = json.loads(response.text) + + if res_json["success"]: + if "data" in res_json: + data = res_json["data"] + time = data["dateList"] + time_new = [] + for elem in time: + time_actual = dt.datetime.utcfromtimestamp(elem / 1000) + time_new.append(time_actual) + + df = pd.DataFrame( + data={ + "date": time_new, + "price": data["priceList"], + **data["dataMap"], + } + ) + df = df.set_index("date") + else: + console.print(f"No data found for {symbol}.\n") + else: + if "secret invalid" in res_json["msg"]: + console.print("[red]Invalid API Key[/red]\n") + else: + console.print(res_json["msg"]) + + elif response.status_code == 429: + console.print("[red]Exceeded number of calls per minute[/red]\n") + elif response.status_code == 429: + console.print( + "[red]IP address autobanned for exceeding calls limit multiple times.[/red]\n" + ) + + return df + + @log_start_end(log=logger) def get_open_interest_per_exchange(symbol: str, interval: int) -> pd.DataFrame: """Returns open interest by exchange for a certain symbol @@ -36,7 +98,7 @@ def get_open_interest_per_exchange(symbol: str, interval: int) -> pd.DataFrame: url = ( api_url - + f"futures/openInterest/chart?&symbol={symbol.upper()}&interval={interval}" + + f"futures/openInterest/chart?symbol={symbol.upper()}&interval={interval}" ) headers = {"coinglassSecret": cfg.API_COINGLASS_KEY} diff --git a/openbb_terminal/cryptocurrency/due_diligence/coinglass_view.py b/openbb_terminal/cryptocurrency/due_diligence/coinglass_view.py index 3da9064c84ea..42a76e5dc373 100644 --- a/openbb_terminal/cryptocurrency/due_diligence/coinglass_view.py +++ b/openbb_terminal/cryptocurrency/due_diligence/coinglass_view.py @@ -9,6 +9,7 @@ from openbb_terminal.config_terminal import theme from openbb_terminal import config_plot as cfgPlot from openbb_terminal.cryptocurrency.due_diligence.coinglass_model import ( + get_funding_rate, get_open_interest_per_exchange, ) from openbb_terminal.decorators import check_api_key @@ -24,6 +25,33 @@ logger = logging.getLogger(__name__) +@log_start_end(log=logger) +@check_api_key(["API_COINGLASS_KEY"]) +def display_funding_rate(symbol: str, export: str = "") -> None: + """Displays funding rate by exchange for a certain cryptocurrency + [Source: https://coinglass.github.io/API-Reference/] + + Parameters + ---------- + symbol : str + Crypto symbol to search funding rate (e.g., BTC) + export : str + Export dataframe data to csv,json,xlsx file""" + df = get_funding_rate(symbol) + if df.empty: + return + + plot_data(df, symbol, f"Exchange {symbol} Funding Rate", "Funding Rate [%]") + console.print("") + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "fundrate", + df, + ) + + @log_start_end(log=logger) @check_api_key(["API_COINGLASS_KEY"]) def display_open_interest(symbol: str, interval: int = 0, export: str = "") -> None: @@ -42,7 +70,12 @@ def display_open_interest(symbol: str, interval: int = 0, export: str = "") -> N if df.empty: return - plot_data(df, symbol) + plot_data( + df, + symbol, + f"Exchange {symbol} Futures Open Interest", + "Open futures value [$B]", + ) console.print("") export_data( @@ -57,6 +90,8 @@ def display_open_interest(symbol: str, interval: int = 0, export: str = "") -> N def plot_data( df: pd.DataFrame, symbol: str, + title: str, + ylabel: str, external_axes: Optional[List[plt.Axes]] = None, ): @@ -84,8 +119,8 @@ def plot_data( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x)) ) ax1.legend(df_without_price.columns, fontsize="x-small", ncol=2) - ax1.set_title(f"Exchange {symbol} Futures Open Interest") - ax1.set_ylabel("Open futures value[$B]") + ax1.set_title(title) + ax1.set_ylabel(ylabel) ax2.plot(df_price.index, df_price) ax2.legend([f"{symbol} price"]) diff --git a/openbb_terminal/cryptocurrency/due_diligence/dd_controller.py b/openbb_terminal/cryptocurrency/due_diligence/dd_controller.py index 523dd750277b..3f6481779286 100644 --- a/openbb_terminal/cryptocurrency/due_diligence/dd_controller.py +++ b/openbb_terminal/cryptocurrency/due_diligence/dd_controller.py @@ -55,7 +55,7 @@ def check_cg_id(symbol: str): class DueDiligenceController(CryptoBaseController): """Due Diligence Controller class""" - CHOICES_COMMANDS = ["load", "oi", "active", "change", "nonzero", "eb"] + CHOICES_COMMANDS = ["load", "fundrate", "oi", "active", "change", "nonzero", "eb"] SPECIFIC_CHOICES = { "cp": [ @@ -183,6 +183,7 @@ def print_help(self): mt.add_cmd("trades", "Coinbase") mt.add_cmd("ex", "CoinPaprika") mt.add_cmd("oi", "Coinglass") + mt.add_cmd("fundrate", "Coinglass") mt.add_cmd("eb", "Glassnode") mt.add_info("_metrics_") @@ -499,6 +500,30 @@ def call_oi(self, other_args): export=ns_parser.export, ) + @log_start_end(log=logger) + def call_fundrate(self, other_args): + """Process fundrate command""" + assert isinstance(self.symbol, str) + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="fundrate", + description=""" + Displays funding rate by exchange for a certain asset + [Source: https://coinglass.github.io/API-Reference/] + """, + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES + ) + + if ns_parser: + coinglass_view.display_funding_rate( + symbol=self.symbol.upper(), + export=ns_parser.export, + ) + @log_start_end(log=logger) def call_info(self, other_args): """Process info command""" diff --git a/website/content/terminal/crypto/dd/fundrate/_index.md b/website/content/terminal/crypto/dd/fundrate/_index.md new file mode 100644 index 000000000000..4fa19d40b9d1 --- /dev/null +++ b/website/content/terminal/crypto/dd/fundrate/_index.md @@ -0,0 +1,11 @@ +``` +usage: fundrate [-h] [--export EXPORT] +``` + +Displays funding rate by exchange for a certain asset [Source: https://coinglass.github.io/API-Reference/] + +``` +optional arguments: + -h, --help show this help message (default: False) + --export EXPORT Export raw data into csv, json, xlsx and figure into png, jpg, pdf, svg (default: ) +``` diff --git a/website/content/terminal/crypto/dd/oi/_index.md b/website/content/terminal/crypto/dd/oi/_index.md index 97a05fa6b555..5d7aaa269ca1 100644 --- a/website/content/terminal/crypto/dd/oi/_index.md +++ b/website/content/terminal/crypto/dd/oi/_index.md @@ -3,7 +3,7 @@ usage: oi [-i {0, 1, 2, 4}] [--export {csv,json,xlsx}] [-h] ``` -Display the open interest per exchange for a certain cryptocurrency. [Source: https://bybt.gitbook.io] +Display the open interest per exchange for a certain cryptocurrency. [Source: https://coinglass.github.io/API-Reference/] Crypto must be loaded (e.g., `load btc`) before running this feature. The total Bitcoin futures open interest across cryptocurrency exchanges, where open interest is calculated as the estimated notional value of all open futures positions, or the aggregate dollar value of outstanding contract specified BTC deliverables. Includes the largest exchanges with trustworthy reporting of exchange volume metrics. diff --git a/website/data/menu/main.yml b/website/data/menu/main.yml index 4b0629a921af..2aa545f703d7 100755 --- a/website/data/menu/main.yml +++ b/website/data/menu/main.yml @@ -748,6 +748,8 @@ main: ref: "/terminal/crypto/dd/change" - name: eb ref: "/terminal/crypto/dd/eb" + - name: fundrate + ref: "/terminal/crypto/dd/fundrate" - name: oi ref: "/terminal/crypto/dd/oi" - name: info From 488944db064327fe23eba334849f79ca3ee04ea4 Mon Sep 17 00:00:00 2001 From: jose-donato Date: Mon, 25 Jul 2022 23:36:12 +0100 Subject: [PATCH 2/3] didier changes --- i18n/en.yml | 2 +- scripts/test_crypto_dd.openbb | 2 ++ .../insider/txt/test_insider_controller/test_print_help.txt | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 926908433c22..93ef5dbbc43b 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -251,7 +251,7 @@ en: stocks/ins/stats: insider stats of the company stocks/ins/act: insider activity over time stocks/ins/lins: last insider trading of the company - stocks/ins/lcb: latest cluster boys + stocks/ins/lcb: latest cluster buys stocks/ins/lpsb: latest penny stock buys stocks/ins/lit: latest insider trading (all filings) stocks/ins/lip: latest insider purchases diff --git a/scripts/test_crypto_dd.openbb b/scripts/test_crypto_dd.openbb index d823cb822dfa..3ee8fffc8526 100644 --- a/scripts/test_crypto_dd.openbb +++ b/scripts/test_crypto_dd.openbb @@ -1,6 +1,8 @@ crypto load btc dd +fundrate +oi nonzero info market diff --git a/tests/openbb_terminal/stocks/insider/txt/test_insider_controller/test_print_help.txt b/tests/openbb_terminal/stocks/insider/txt/test_insider_controller/test_print_help.txt index 9c71be5d2065..a58049a37b13 100644 --- a/tests/openbb_terminal/stocks/insider/txt/test_insider_controller/test_print_help.txt +++ b/tests/openbb_terminal/stocks/insider/txt/test_insider_controller/test_print_help.txt @@ -13,7 +13,7 @@ Ticker: [unvl] lins last insider trading of the company[/unvl] [Finviz] Last Insiders: - lcb latest cluster boys [Open Insider] + lcb latest cluster buys [Open Insider] lpsb latest penny stock buys [Open Insider] lit latest insider trading (all filings) [Open Insider] lip latest insider purchases [Open Insider] From db4d66de0ab5a6ae148dc522b9c99c4e23783115 Mon Sep 17 00:00:00 2001 From: jose-donato Date: Mon, 25 Jul 2022 23:43:53 +0100 Subject: [PATCH 3/3] tests --- .../cryptocurrency/due_diligence/test_dd_controller.py | 7 +++++++ .../txt/test_dd_controller/test_print_help.txt | 1 + 2 files changed, 8 insertions(+) diff --git a/tests/openbb_terminal/cryptocurrency/due_diligence/test_dd_controller.py b/tests/openbb_terminal/cryptocurrency/due_diligence/test_dd_controller.py index 3886c2fa1c30..dd694862ff59 100644 --- a/tests/openbb_terminal/cryptocurrency/due_diligence/test_dd_controller.py +++ b/tests/openbb_terminal/cryptocurrency/due_diligence/test_dd_controller.py @@ -302,6 +302,13 @@ def test_call_func_expect_queue(expected_queue, func, queue, mocker): [], dict(), ), + ( + "call_fundrate", + [], + "coinglass_view.display_funding_rate", + [], + dict(), + ), ( "call_oi", [], diff --git a/tests/openbb_terminal/cryptocurrency/due_diligence/txt/test_dd_controller/test_print_help.txt b/tests/openbb_terminal/cryptocurrency/due_diligence/txt/test_dd_controller/test_print_help.txt index d05a49c5384c..7c9da447a369 100644 --- a/tests/openbb_terminal/cryptocurrency/due_diligence/txt/test_dd_controller/test_print_help.txt +++ b/tests/openbb_terminal/cryptocurrency/due_diligence/txt/test_dd_controller/test_print_help.txt @@ -22,6 +22,7 @@ Market: trades last trades [Coinbase] ex all exchanges where loaded coin is listed [CoinPaprika] oi open interest per exchange [Coinglass] + fundrate funding rate per exchange [Coinglass] eb total balance held on exchanges (in percentage and units) [Glassnode] Metrics: mcapdom market cap dominance [Messari]