Open crypto insterest by exchange [Source: bybt.com] (#868)

* fix: small issues

* fix: repeated code

* feat: added new oi feature; needed to refactor a bit

* fix: test coingecko fixed

* fix: pylint issue

* fix: added entry to main.yml

* fix: added image to hugo markdown
This commit is contained in:
jose-donato
2021-10-27 11:11:49 +01:00
committed by GitHub
parent 9ef2a31dfc
commit a04e833e7e
13 changed files with 436 additions and 37 deletions

View File

@@ -103,5 +103,8 @@ API_WHALE_ALERT_KEY = os.getenv("GT_API_WHALE_ALERT_KEY") or "REPLACE_ME"
# https://docs.glassnode.com/basic-api/api-key#how-to-get-an-api-key
API_GLASSNODE_KEY = os.getenv("GT_API_GLASSNODE_KEY") or "REPLACE_ME"
# https://bybt.gitbook.io/bybt/api-key
API_BYBT_KEY = os.getenv("GT_API_BYBT_KEY") or "REPLACE_ME"
# https://github.com/EverexIO/Ethplorer/wiki/Ethplorer-API
API_ETHPLORER_KEY = os.getenv("GT_API_ETHPLORER_KEY") or "freekey"

View File

@@ -89,6 +89,7 @@ class CryptoController:
self.crypto_parser = argparse.ArgumentParser(add_help=False, prog="crypto")
self.crypto_parser.add_argument("cmd", choices=self.CHOICES)
self.symbol = ""
self.current_coin = ""
self.current_df = pd.DataFrame()
self.current_currency = ""
@@ -226,7 +227,7 @@ What do you want to do?
if arg in other_args:
other_args.remove(arg)
self.current_coin, self.source = load(
self.current_coin, self.source, self.symbol = load(
coin=ns_parser.coin, source=ns_parser.source
)
@@ -725,7 +726,7 @@ What do you want to do?
def call_dd(self, _):
"""Process dd command"""
if self.current_coin:
dd = dd_controller.menu(self.current_coin, self.source)
dd = dd_controller.menu(self.current_coin, self.source, self.symbol)
if dd is False:
self.print_help()
else:

View File

@@ -144,7 +144,7 @@ def _create_closest_match_df(
def load(
coin: str,
source: str,
) -> Tuple[Union[Optional[str], pycoingecko_model.Coin], Any]:
) -> Tuple[Union[Optional[str], pycoingecko_model.Coin], Optional[Any], Optional[Any]]:
"""Load cryptocurrency from given source. Available sources are: CoinGecko, CoinPaprika, Coinbase and Binance.
Loading coin from Binance and CoinPaprika means validation if given coins exists in chosen source,
@@ -161,16 +161,17 @@ def load(
Returns
-------
Tuple[Union[str, pycoingecko_model.Coin], Any]
Tuple[Union[str, pycoingecko_model.Coin], str, str]
- str or Coin object for provided coin
- str with source of the loaded data. CoinGecko, CoinPaprika, or Binance
- str with
"""
current_coin = "" # type: Optional[Any]
if source == "cg":
current_coin = pycoingecko_model.Coin(coin)
return current_coin, source
coingecko = pycoingecko_model.Coin(coin)
return coingecko, source, coingecko.symbol
if source == "bin":
parsed_coin = coin.upper()
@@ -179,13 +180,13 @@ def load(
print(f"Coin found : {current_coin}\n")
else:
print(f"Couldn't find coin with symbol {current_coin}\n")
return current_coin, source
return current_coin, source, parsed_coin
if source == "cp":
paprika_coins = get_list_of_coins()
paprika_coins_dict = dict(zip(paprika_coins.id, paprika_coins.symbol))
current_coin, _ = coinpaprika_model.validate_coin(coin, paprika_coins_dict)
return current_coin, source
current_coin, symbol = coinpaprika_model.validate_coin(coin, paprika_coins_dict)
return current_coin, source, symbol
if source == "cb":
coinbase_coin = coin.upper()
@@ -196,9 +197,9 @@ def load(
print(f"Coin found : {current_coin}\n")
else:
print(f"Couldn't find coin with symbol {current_coin}\n")
return current_coin, source
return current_coin, source, coin
return current_coin, None
return current_coin, None, None
# TODO: Find better algorithm then difflib.get_close_matches to find most similar coins

View File

@@ -0,0 +1,45 @@
import json
import datetime as dt
import pandas as pd
import requests
from gamestonk_terminal import config_terminal as cfg
def get_open_interest_per_exchange(symbol: str, interval: int) -> pd.DataFrame:
"""Returns open interest by exchange for a certain symbol
[Source: https://bybt.gitbook.io]
Parameters
----------
symbol : str
Crypto Symbol to search open interest futures (e.g., BTC)
interval : int
Interval frequency (e.g., 0)
Returns
-------
pd.DataFrame
open interest by exchange and price
"""
url = f"http://open-api.bybt.com/api/pro/v1/futures/openInterest/chart?&symbol={symbol.upper()}&interval={interval}"
headers = {"bybtSecret": cfg.API_BYBT_KEY}
response = requests.request("GET", url, headers=headers)
if response.status_code == 200:
res_json = json.loads(response.text)
if res_json["msg"] == "success":
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")
return df
return pd.DataFrame()

View File

@@ -0,0 +1,63 @@
import os
from matplotlib import pyplot as plt, dates as mdates
import pandas as pd
from gamestonk_terminal.cryptocurrency.due_diligence.bybt_model import (
get_open_interest_per_exchange,
)
from gamestonk_terminal.helper_funcs import export_data, plot_autoscale
from gamestonk_terminal import config_plot as cfgPlot
def display_open_interest(symbol: str, interval: int, export: str) -> None:
"""Displays open interest by exchange for a certain cryptocurrency
[Source: https://bybt.gitbook.io]
Parameters
----------
symbol : str
Crypto symbol to search open interest (e.g., BTC)
interval : int
Interval frequency (e.g., 0)
export : str
Export dataframe data to csv,json,xlsx file"""
df = get_open_interest_per_exchange(symbol, interval)
if df.empty:
print("Error in glassnode request")
else:
plot_data(df, symbol)
print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"oi",
df,
)
def plot_data(df: pd.DataFrame, symbol: str):
df_price = df[["price"]].copy()
df_without_price = df.drop("price", 1)
_, ax1 = plt.subplots(figsize=plot_autoscale(), dpi=cfgPlot.PLOT_DPI)
plt.plot(df_without_price.index, df_without_price / 1e9)
plt.legend(df_without_price.columns)
ax2 = ax1.twinx()
plt.grid()
plt.plot(df_price.index, df_price, lw=3, c="k")
plt.legend([f"{symbol} price"], loc=1)
ax1.set_ylabel(
"Estimated notional value of all open futures positions [$ billions]"
)
ax2.set_ylabel(f"{symbol} Price [$]")
plt.xlim([df_price.index[0], df_price.index[-1]])
plt.title(f"Exchange {symbol} Futures Open Interest")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=1))
plt.gcf().autofmt_xdate()
plt.show()

View File

@@ -10,6 +10,7 @@ from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.menu import session
from gamestonk_terminal.cryptocurrency.due_diligence import (
bybt_view,
pycoingecko_view,
coinpaprika_view,
binance_view,
@@ -30,15 +31,14 @@ import gamestonk_terminal.config_terminal as cfg
class DueDiligenceController:
CHOICES = [
"?",
"cls",
"help",
"q",
"quit",
"chart",
CHOICES = ["?", "cls", "help", "q", "quit", "chart"]
CHOICES_COMMANDS = [
"oi",
]
CHOICES += CHOICES_COMMANDS
SPECIFIC_CHOICES = {
"cp": [
"events",
@@ -72,7 +72,7 @@ class DueDiligenceController:
"bin": binance_view,
}
def __init__(self, coin=None, source=None):
def __init__(self, coin=None, source=None, symbol=None):
"""CONSTRUCTOR"""
self._dd_parser = argparse.ArgumentParser(add_help=False, prog="dd")
@@ -81,6 +81,7 @@ class DueDiligenceController:
self.current_currency = None
self.current_df = pd.DataFrame()
self.source = source
self.symbol = symbol
self.CHOICES.extend(self.SPECIFIC_CHOICES[self.source])
@@ -94,6 +95,9 @@ Due Diligence:
?/help show this menu again
q quit this menu, and shows back to main menu
quit quit to abandon the program
Bybt:
oi open interest per exchange
"""
if self.source == "cp":
help_text += """
@@ -180,6 +184,58 @@ Coinbase:
"""Process Quit command - quit the program."""
return True
def call_oi(self, other_args):
"""Process oi command"""
if self.symbol:
assert isinstance(self.symbol, str)
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="oi",
description="""
Displays open interest by exchange for a certain asset
[Source: https://bybt.gitbook.io]
""",
)
parser.add_argument(
"-i",
"--interval",
dest="interval",
type=int,
help="Frequency interval. Default: 0",
default=0,
choices=[0, 1, 2, 4],
)
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
bybt_view.display_open_interest(
symbol=self.symbol.upper(),
interval=ns_parser.interval,
export=ns_parser.export,
)
except Exception as e:
print(e)
else:
print(
"No coin selected. Use 'load' to load the coin you want to look at.\n"
)
def call_info(self, other_args):
"""Process info command"""
if self.current_coin:
@@ -1364,10 +1420,10 @@ Coinbase:
)
def menu(coin=None, source=None):
def menu(coin=None, source=None, symbol=None):
source = source if source else "cg"
dd_controller = DueDiligenceController(coin=coin, source=source)
dd_controller = DueDiligenceController(coin=coin, source=source, symbol=symbol)
dd_controller.print_help()
while True:

View File

@@ -1,7 +1,7 @@
"""CoinGecko model"""
__docformat__ = "numpy"
from typing import Union, Any, Dict, List, Optional
from typing import Tuple, Union, Any, Dict, List, Optional
import regex as re
import pandas as pd
from pycoingecko import CoinGeckoAPI
@@ -44,7 +44,7 @@ class Coin:
def __init__(self, symbol: str):
self.client = CoinGeckoAPI()
self._coin_list = self.client.get_coins_list()
self.coin_symbol = self._validate_coin(symbol)
self.coin_symbol, self.symbol = self._validate_coin(symbol)
if self.coin_symbol:
self.coin: Dict[Any, Any] = self._get_coin_info()
@@ -52,7 +52,7 @@ class Coin:
def __str__(self):
return f"{self.coin_symbol}"
def _validate_coin(self, symbol: str) -> str:
def _validate_coin(self, search_coin: str) -> Tuple[Optional[Any], Optional[Any]]:
"""Validate if given coin symbol or id exists in list of available coins on CoinGecko.
If yes it returns coin id. [Source: CoinGecko]
@@ -63,19 +63,22 @@ class Coin:
Returns
-------
str
id of the coin on CoinGecko service.
Tuple[str, str]
- str with coin
- str with symbol
"""
coin = None
symbol = None
for dct in self._coin_list:
if symbol.lower() in list(dct.values()):
if search_coin.lower() in list(dct.values()):
coin = dct.get("id")
symbol = dct.get("symbol")
print(f"Coin found : {coin} with symbol {symbol}\n")
break
if not coin:
raise ValueError(f"Could not find coin with the given id: {symbol}\n")
return coin
return coin, symbol
def coin_list(self) -> list:
"""List all available coins [Source: CoinGecko]

View File

@@ -1,6 +1,5 @@
import os
from matplotlib import pyplot as plt
import pandas as pd
from gamestonk_terminal.cryptocurrency.onchain.glassnode_model import (
get_active_addresses,
)
@@ -45,15 +44,9 @@ def display_active_addresses(
def plot_data(df, asset):
df = df.set_index("t")
df.index = pd.to_datetime(df.index, unit="s")
df = df.loc[df.index > "2010-1-1"]
df.reset_index(inplace=True)
_, main_ax = plt.subplots(figsize=plot_autoscale(), dpi=cfgPlot.PLOT_DPI)
main_ax.plot(df["t"], df["v"], linewidth=0.5)
main_ax.set_yscale("log")
main_ax.grid(True)
main_ax.set_title(f"Active {asset} addresses over time")

View File

@@ -71,7 +71,6 @@ class TechnicalAnalysisController:
self.interval = interval
self.stock = stock
self.stock["Adj Close"] = stock["Close"]
print(self.stock)
self.ta_parser = argparse.ArgumentParser(add_help=False, prog="ta")
self.ta_parser.add_argument(

View File

@@ -0,0 +1,208 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate, br
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.pro.coinbase.com/products
response:
body:
string: !!binary |
H4sIAAAAAAAAA+1da3PbxpL9Kyx9thUCJPjINxCEKFziQQOgAnFry8VYckoVmvTqkcfd2v++NaDi
2Ll9hOnRiIyC9keNKI3VNTPdp0+f81//e3JzdfL9SVievw2X+cmbkx/Xd9fvPzzc3l5vP/y+Xzl5
c/I/D7v7b7/85zd/utm+v7v59/XJ9yfd0263646/rKx/+2PFGXS7X37OzfbD7fWn6+39/iPOH9//
l6/v/6nVq5u7z5v17++360/X+z19t9+A+t2f1rc/X9+///iwvbqrPzjqq5X1b39dcbz6B9aLtz/d
bN9fb9c/bq6vTr7/uN7cXb85+fjb+7t79aUPu5vtl6/W/4vNzefP65+u33++vv1wvb1f/7T/7zqP
mzx5c/J5d3f/frfd/P7lg5ubTzd/+dKH9fbD9ebbr93frq9utj+9v7q5+3Y7d/fr+we18d12c7O9
PvnjK+8/Xd/d7Xdw8uZk/fDh/ma3ff9pd3X9+NH/e/MY1mVRvl0W05KI67Ioqbh+/d3fBHZMRdX1
Hv/zZFxhYImQLovyu8ffTcTUAQHlxfP+9qEhnF1HM5z7H3XgaEZZWYFTqpb0j6njUSe09+X/TkcT
xJMIptqN0QFt2/kMzlfofAbnK8b57BEBHTeEE5xOIp7B+erFD+frD+aZnycqmkQw1RKIJnhF+0RA
PcfgDSXCqXbz3f5XSzhhONMlCGa61A9l79TBVy37aKJ8KF1KOJvCGZbB20kZkBluQAX0q2/+9mw6
Q+psPv1ymuS4wXf7LZBPqPqUC2Lb+0fFNXu47YRl0NndXl3fdn7c7X6+66xvrzvb3a+dm23n48Nm
8/bx53dU4E87sdrUm87+r9JZb686d/e7z/sfsP/serOpP7/+ZX2zUTs61UukWXn0EdNo1lXw5be3
I4tehPkCJV1qjVUVdcnrfdS181Cr7TyReHl/u6v9KAGd+NNZmKOQ7lefH9SRpeRrvx+JalNUnSgN
zsGdW69xbt0eVR95Y0uXbr0dycCaM7A6noE+yPj1d2uhjO7IMsr4uANuVNsU1h+Csxm6fNUa6+ql
bl633zV4T4mAqt3IxduIGacRSnXTiAVi9Mlo2i19l2nEvnlb1wb4IV6mPqh+6zVW/Uv3d4YNBTAr
Sao3ZVr+ui2KbFWu3s4mCyKuVUnix19987cX74AKqlFDgL58q3L13f6XkwEdupIl7auZtAQ9nkla
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
B5bwGXVI31mL6dEkOBfLAhTQ//5/3YKYNQFbAgA=
headers:
Access-Control-Allow-Headers:
- Content-Type, Accept, cb-session, cb-fp, cb-form-factor
Access-Control-Allow-Methods:
- GET,POST,DELETE,PUT
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- cb-before, cb-after, cb-gdpr
Access-Control-Max-Age:
- '7200'
CF-Cache-Status:
- HIT
CF-RAY:
- 6a4888296c0003c2-LIS
Cache-Control:
- public, max-age=5, must-revalidate
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 27 Oct 2021 02:35:35 GMT
Etag:
- W/"25b01-aN09APztSve2s3qUAs3Utjcwcfc"
Expect-CT:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server:
- cloudflare
Strict-Transport-Security:
- max-age=15552000; includeSubDomains
Transfer-Encoding:
- chunked
Vary:
- Accept-Encoding
X-Content-Type-Options:
- nosniff
X-Dns-Prefetch-Control:
- 'off'
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Xss-Protection:
- 1; mode=block
status:
code: 200
message: OK
version: 1

View File

@@ -34,7 +34,7 @@ def get_bitcoin(mock_load):
with open("tests/data/btc_usd_test_data.json", encoding="utf8") as f:
sample_return = json.load(f)
mock_load.return_value = sample_return
coin, _ = load(coin="bitcoin", source="cg")
coin, _, _ = load(coin="bitcoin", source="cg")
return coin

View File

@@ -0,0 +1,25 @@
```
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]
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.
Interval:
- ALL: 0
- 1H: 2
- 4H: 1
- 12H: 4
```
optional arguments:
-i INTERV --interval INTERV Interval frequency (default: 0)
--export {csv,json,xlsx} Export dataframe data to csv,json,xlsx file (default: )
-h, --help show this help message (default: False)
```
<img width="1014" alt="Open Interest across crypto exchanges" src="https://user-images.githubusercontent.com/43375532/138989466-bfda67c8-74fd-497a-add8-67bab1149fa8.png">

View File

@@ -791,6 +791,8 @@ main:
- name: due diligence
ref: "/cryptocurrency/due_diligence"
sub:
- name: oi
ref: "/cryptocurrency/due_diligence/oi"
- name: info
ref: "/cryptocurrency/due_diligence/info"
- name: market