Files
OpenBB/openbb_terminal/cryptocurrency/due_diligence/binance_model.py
montezdesousa 475ebb5acd [WIP] Migrate user, feature flags and configurations to dataclass (#4309)
* implement user and change is guest

* replace User methods

* move remaining functions to user

* fix bug

* portfolio test

* fix tests

* fix tests

* uncomment skip

* ruff

* start credentials model implementation

* change deault structure

* refacto quandl

* change default struct and file names

* bug

* start using global user

* add comments

* move update flair

* change cfg references in keys model

* reddit & fmp

* refactore additional keys

* remaing config keys

* remove unsude imports and fix hub keys

* ruff

* fix line too long

* unblock unittests

* fix keys model tests

* remove os patch

* fix account controller tests

* fix account controller tests

* fix account model

* account fixed

* fix user tests

* User Model

* User Model

* User Model

* Move session folder

* User Model : grouping the models

* User Model : fix bugs

* Config Plot + bug fix

* User Model : Refactoring plots

* Feature flags

* Remove dup

* clean comments a fix some vars

* fix feature flags controller

* refactor obbff from settings controller

* refactor a bunch of obbff variables

* fix bug blocking terminal

* fix integration tests

* refactor controllers with obbff

* refactor remaining ffs

* remove comments

* log not started

* mispelled variable

* set current user on local model

* User Model : moving files + updating

* User Preferences

* User : Refactor is_guest function + bug fix

* User : refactor is_guest function

* Fix conftest.py

* remove lost obbffs

* typo on fileoverwrite

* Plot config: move variables and start plot dpi

* User : tests

* refactor plot dpi references

* remove plot dpi imports

* refactor some config terminal leftover

* /account/sync : fix bug

* remove configs reload

* start path refactor

* installation paths vs user paths

* remove cfg_plot

* Tests : User Refactoring

* user prefix only for preferences

* user prefix only for preferences

* move user paths

* remove comment

* update apply remote configs

* fix tz not updating

* save some copys

* small fix

* create interface for credentials and preferences

* wrong docstrings fixed

* ruff core

* fix some pref setting

* login is better

* ruff

* ruff

* remove Literal

* add small comment

* Tests : User Refactoring

* Credentials Model : add DataBento

* Fix helper_funcs

* Fixing code

* Tests : fixing

* User Model : freezing the models

* Fixed Income + Databento

* Tests : fixing keys

* black

* ruff

* Tests : user model

* Tests : user model

* Fix linting

* Fix linting

* Linting

* Linting

* Fixing code and tests

* Fix tests

* mypy

* SDK

* Clean ruff cache

* Fix syntax issue

* Update fred_view

* Black

* Linting

* Update code

* Update tests

* Linting

* Linting

* Tests

* Black

* Linting

* Linting

* Mock os.listdir to avoid looking for file that doesnt exist

* Mock options paths

* lint

* Tests : fix

* Code : update

* Tests + Linting

* Tests

* Ruff

* Code : update

* Tests

* Code : update

* Fix workflow

* Code : update

---------

Co-authored-by: Chavithra PARANA <chavithra@gmail.com>
Co-authored-by: luqazino@gmail.com <luqazino@gmail.com>
Co-authored-by: James Maslek <jmaslek11@gmail.com>
2023-03-05 00:37:19 +01:00

236 lines
7.3 KiB
Python

"""Binance model"""
__docformat__ = "numpy"
import argparse
import logging
from collections import defaultdict
from typing import List, Tuple, Union
import pandas as pd
from binance.client import Client
from binance.exceptions import BinanceAPIException
from openbb_terminal.core.session.current_user import get_current_user
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
@check_api_key(["API_BINANCE_KEY", "API_BINANCE_SECRET"])
def _get_trading_pairs() -> List[dict]:
"""Helper method that return all trading pairs on binance. Methods ause this data for input for e.g
building dataframe with all coins, or to build dict of all trading pairs. [Source: Binance]
Returns
-------
List[dict]
list of dictionaries in format:
[
{'symbol': 'ETHBTC', 'status': 'TRADING', 'baseAsset': 'ETH', 'baseAssetPrecision': 8,
'quoteAsset': 'BTC', 'quotePrecision': 8, 'quoteAssetPrecision': 8,
'baseCommissionPrecision': 8, 'quoteCommissionPrecision': 8,
'orderTypes': ['LIMIT', 'LIMIT_MAKER', 'MARKET', 'STOP_LOSS_LIMIT', 'TAKE_PROFIT_LIMIT'],
'icebergAllowed': True,
'ocoAllowed': True,
'quoteOrderQtyMarketAllowed': True,
'isSpotTradingAllowed': True,
'isMarginTradingAllowed': True,
'filters': [{'filterType': 'PRICE_FILTER', 'minPrice': '0.00000100',
'maxPrice': '922327.00000000', 'tickSize': '0.00000100'},
{'filterType': 'PERCENT_PRICE', 'multiplierUp': '5', 'multiplierDown': '0.2', 'avgPriceMins': 5},
{'filterType': 'LOT_SIZE', 'minQty': '0.00100000', 'maxQty': '100000.00000000', 'stepSize': '0.00100000'},
{'filterType': 'MIN_NOTIONAL', 'minNotional': '0.00010000', 'applyToMarket': True, 'avgPriceMins': 5},
{'filterType': 'ICEBERG_PARTS', 'limit': 10}, {'filterType': 'MARKET_LOT_SIZE', 'minQty': '0.00000000',
'maxQty': '930.49505347', 'stepSize': '0.00000000'}, {'filterType': 'MAX_NUM_ORDERS', 'maxNumOrders': 200},
{'filterType': 'MAX_NUM_ALGO_ORDERS', 'maxNumAlgoOrders': 5}], 'permissions': ['SPOT', 'MARGIN']},
...
]
"""
current_user = get_current_user()
client = Client(
current_user.credentials.API_BINANCE_KEY,
current_user.credentials.API_BINANCE_SECRET,
)
ex_info = client.get_exchange_info()["symbols"]
trading_pairs = [p for p in ex_info if p["status"] == "TRADING"]
return trading_pairs
@log_start_end(log=logger)
@check_api_key(["API_BINANCE_KEY", "API_BINANCE_SECRET"])
def get_all_binance_trading_pairs() -> pd.DataFrame:
"""Returns all available pairs on Binance in DataFrame format. DataFrame has 3 columns symbol, baseAsset, quoteAsset
example row: ETHBTC | ETH | BTC
[Source: Binance]
Returns
-------
pd.DataFrame
All available pairs on Binance
Columns: symbol, baseAsset, quoteAsset
"""
trading_pairs = _get_trading_pairs()
return pd.DataFrame(trading_pairs)[["symbol", "baseAsset", "quoteAsset"]]
@log_start_end(log=logger)
@check_api_key(["API_BINANCE_KEY", "API_BINANCE_SECRET"])
def get_binance_available_quotes_for_each_coin() -> dict:
"""Helper methods that for every coin available on Binance add all quote assets. [Source: Binance]
Returns
-------
dict
All quote assets for given coin
{'ETH' : ['BTC', 'USDT' ...], 'UNI' : ['ETH', 'BTC','BUSD', ...]
"""
trading_pairs = _get_trading_pairs()
results = defaultdict(list)
for pair in trading_pairs:
results[pair["baseAsset"]].append(pair["quoteAsset"])
return results
@log_start_end(log=logger)
@check_api_key(["API_BINANCE_KEY", "API_BINANCE_SECRET"])
def check_valid_binance_str(symbol: str) -> str:
"""Check if symbol is in defined binance. [Source: Binance]
Returns
-------
str
Symbol
"""
current_user = get_current_user()
client = Client(
current_user.credentials.API_BINANCE_KEY,
current_user.credentials.API_BINANCE_SECRET,
)
try:
client.get_avg_price(symbol=symbol.upper())
return symbol.upper()
except BinanceAPIException as e:
logger.exception("%s is not a valid binance symbol", str(symbol))
raise argparse.ArgumentTypeError(
f"{symbol} is not a valid binance symbol"
) from e
@log_start_end(log=logger)
@check_api_key(["API_BINANCE_KEY", "API_BINANCE_SECRET"])
def show_available_pairs_for_given_symbol(
symbol: str = "ETH",
) -> Tuple[Union[str, None], list]:
"""Return all available quoted assets for given symbol. [Source: Binance]
Parameters
----------
symbol: str
Uppercase symbol of coin e.g BTC, ETH, UNI, LUNA, DOT ...
Returns
-------
Tuple[Union[str, None], list]
Tuple of symbol,
list of quoted assets for given symbol: ["BTC", "USDT" , "BUSD"]
"""
symbol_upper = symbol.upper()
pairs = get_binance_available_quotes_for_each_coin()
for k, v in pairs.items():
if k == symbol_upper:
return k, v
return None, []
@log_start_end(log=logger)
@check_api_key(["API_BINANCE_KEY", "API_BINANCE_SECRET"])
def get_order_book(
from_symbol: str,
limit: int = 100,
to_symbol: str = "USDT",
) -> pd.DataFrame:
"""Get order book for currency. [Source: Binance]
Parameters
----------
from_symbol: str
Cryptocurrency symbol
limit: int
Limit parameter. Adjusts the weight
to_symbol: str
Quote currency (what to view coin vs)
Returns
-------
pd.DataFrame
Dataframe containing orderbook
"""
pair = from_symbol + to_symbol
current_user = get_current_user()
client = Client(
current_user.credentials.API_BINANCE_KEY,
current_user.credentials.API_BINANCE_SECRET,
)
try:
market_book = client.get_order_book(symbol=pair, limit=limit)
except BinanceAPIException:
console.print(f"{to_symbol} is not a valid binance symbol")
return pd.DataFrame(market_book)
@log_start_end(log=logger)
@check_api_key(["API_BINANCE_KEY", "API_BINANCE_SECRET"])
def get_balance(
from_symbol: str,
to_symbol: str = "USDT",
) -> pd.DataFrame:
"""Get account holdings for asset. [Source: Binance]
Parameters
----------
from_symbol: str
Cryptocurrency
to_symbol: str
Cryptocurrency
Returns
-------
pd.DataFrame
Dataframe with account holdings for an asset
"""
current_user = get_current_user()
client = Client(
current_user.credentials.API_BINANCE_KEY,
current_user.credentials.API_BINANCE_SECRET,
)
pair = from_symbol + to_symbol
current_balance = client.get_asset_balance(asset=from_symbol)
if current_balance is None:
console.print("Check loaded coin\n")
return pd.DataFrame()
last_price = client.get_ticker(symbol=pair).get("lastPrice")
amounts = [float(current_balance["free"]), float(current_balance["locked"])]
df = pd.DataFrame(amounts)
df.columns = ["Amount"]
df.index = ["Free", "Locked"]
if last_price:
last_price = float(last_price)
df[f"Amount [{to_symbol}]"] = df["Amount"].mul(last_price)
df["Percent"] = df["Amount"].mul(100).div(df["Amount"].sum(axis=0)).round(3)
return df