Skip to content

Commit

Permalink
Merge branch 'development' into fix/Beaxy_float_rounding
Browse files Browse the repository at this point in the history
  • Loading branch information
ccraighead authored Mar 31, 2021
2 parents 3dafda5 + d6bf525 commit 21b4a4e
Show file tree
Hide file tree
Showing 133 changed files with 7,669 additions and 1,030 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ We created hummingbot to promote **decentralized market-making**: enabling membe

| logo | id | name | ver | doc | status |
|:---:|:---:|:---:|:---:|:---:|:---:|
| <img src="assets/ascend_ex_logo.png" alt="AscendEx" width="90" /> | ascend_ex | [AscendEx](https://ascendex.com/en/global-digital-asset-platform) | 1 | [API](https://ascendex.github.io/ascendex-pro-api/#ascendex-pro-api-documentation) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/beaxy_logo.png" alt="Beaxy" width="90" /> | beaxy | [Beaxy](https://beaxy.com/) | 2 | [API](https://beaxyapiv2trading.docs.apiary.io/) |![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="https://i.ibb.co/m0YDQLd/Screen-Shot-2019-03-14-at-10-53-42-AM.png" alt="Binance" width="90" /> | binance | [Binance](https://www.binance.com/) | 3 | [API](https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/binanceus_logo.png" alt="Binance US" width="90" /> | binance_us | [Binance US](https://www.binance.com/) | 3 | [API](https://github.com/binance-us/binance-official-api-docs/blob/master/rest-api.md) |![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/binance_perpetual_logo.png" alt="Binance Perpetual" width="90" /> | binance_perpetual | [Binance Futures](https://www.binance.com/) | 1 | [API](https://binance-docs.github.io/apidocs/futures/en/) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
|<img src="assets/bittrex_logo.png" alt="Bittrex Global" width="90" height="30" />| bittrex | [Bittrex Global](https://global.bittrex.com/) | 3 | [API](https://bittrex.github.io/api/v3) |![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/bitfinex_logo.png" alt="Bitfinex" width="90" /> | bitfinex | [Bitfinex](https://www.bitfinex.com/) | 2 | [API](https://docs.bitfinex.com/docs/introduction) |![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/bitmax_logo.png" alt="BitMax" width="90" /> | bitmax | [BitMax](https://bitmax.io/en/global-digital-asset-platform) | 1 | [API](https://bitmax-exchange.github.io/bitmax-pro-api/#bitmax-pro-api-documentation) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/blocktane_logo.png" alt="Blocktane" width="90" /> | blocktane | [Blocktane](https://blocktane.io/) | 2 | [API](https://blocktane.io/api) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="https://i.ibb.co/h9JdGDW/cbp.jpg" alt="Coinbase Pro" width="90" /> | coinbase_pro | [Coinbase Pro](https://pro.coinbase.com/) | * | [API](https://docs.pro.coinbase.com/) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/cryptocom_logo.png" alt="Crypto.com" width="90" /> | crypto_com | [Crypto.com](https://crypto.com/exchange) | 2 | [API](https://exchange-docs.crypto.com/#introduction) |![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/dydx_logo.png" alt="DyDx" width="90" /> | dydx | [dy/dx](https://dydx.exchange/) | 1 | [API](https://docs.dydx.exchange/) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/eterbase_logo.png" alt="Eterbase" width="90" /> | eterbase | [Eterbase](https://www.eterbase.com/) | * | [API](https://developers.eterbase.exchange/?version=latest) |![RED](https://via.placeholder.com/15/f03c15/?text=+) |
| <img src="assets/hitbtc_logo.png" alt="HitBTC" width="90" /> | hitbtc | [HitBTC](https://hitbtc.com/) | 2 | [API](https://api.hitbtc.com/) | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
|<img src="assets/huobi_logo.png" alt="Huobi Global" width="90" />| huobi | [Huobi Global](https://www.hbg.com) | 1 | [API](https://huobiapi.github.io/docs/spot/v1/en/) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/kucoin_logo.png" alt="KuCoin" width="90" /> | kucoin | [KuCoin](https://www.kucoin.com/) | 1 | [API](https://docs.kucoin.com/#general) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/kraken_logo.png" alt="Kraken" width="90" /> | kraken | [Kraken](https://www.kraken.com/) | 1 | [API](https://www.kraken.com/features/api) |![GREEN](https://via.placeholder.com/15/008000/?text=+) |
Expand Down
Binary file added assets/ascend_ex_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/bitmax_logo.png
Binary file not shown.
Binary file added assets/hitbtc_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion bin/hummingbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async def main():
# This init_logging() call is important, to skip over the missing config warnings.
init_logging("hummingbot_logs.yml")

read_system_configs_from_yml()
await read_system_configs_from_yml()

hb = HummingbotApplication.main_application()

Expand Down
4 changes: 2 additions & 2 deletions bin/hummingbot_quickstart.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ async def quick_start(args):
await Security.wait_til_decryption_done()
await create_yml_files()
init_logging("hummingbot_logs.yml")
read_system_configs_from_yml()
await read_system_configs_from_yml()

hb = HummingbotApplication.main_application()
# Todo: validate strategy and config_file_name before assinging

if config_file_name is not None:
hb.strategy_file_name = config_file_name
hb.strategy_name = update_strategy_config_map_from_file(os.path.join(CONF_FILE_PATH, config_file_name))
hb.strategy_name = await update_strategy_config_map_from_file(os.path.join(CONF_FILE_PATH, config_file_name))

# To ensure quickstart runs with the default value of False for kill_switch_enabled if not present
if not global_config_map.get("kill_switch_enabled"):
Expand Down
4 changes: 4 additions & 0 deletions conf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@
crypto_com_api_key = os.getenv("CRYPTO_COM_API_KEY")
crypto_com_secret_key = os.getenv("CRYPTO_COM_SECRET_KEY")
# HitBTC Tests
hitbtc_api_key = os.getenv("HITBTC_API_KEY")
hitbtc_secret_key = os.getenv("HITBTC_SECRET_KEY")
# Wallet Tests
test_erc20_token_address = os.getenv("TEST_ERC20_TOKEN_ADDRESS")
web3_test_private_key_a = os.getenv("TEST_WALLET_PRIVATE_KEY_A")
Expand Down
4 changes: 3 additions & 1 deletion hummingbot/client/command/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .open_orders_command import OpenOrdersCommand
from .trades_command import TradesCommand
from .pnl_command import PnlCommand
from .rate_command import RateCommand


__all__ = [
Expand All @@ -42,5 +43,6 @@
GenerateCertsCommand,
OpenOrdersCommand,
TradesCommand,
PnlCommand
PnlCommand,
RateCommand,
]
49 changes: 18 additions & 31 deletions hummingbot/client/command/balance_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
)
from hummingbot.client.config.config_validators import validate_decimal, validate_exchange
from hummingbot.market.celo.celo_cli import CeloCLI
from hummingbot.core.utils.market_price import usd_value
from hummingbot.client.performance import smart_round
from hummingbot.core.rate_oracle.rate_oracle import RateOracle
import pandas as pd
from decimal import Decimal
from typing import TYPE_CHECKING, Dict, Optional, List
Expand Down Expand Up @@ -76,6 +77,7 @@ def balance(self,
save_to_yml(file_path, config_map)

async def show_balances(self):
total_col_name = f'Total ({RateOracle.global_token_symbol})'
self._notify("Updating balances, please wait...")
all_ex_bals = await UserBalances.instance().all_balances_all_exchanges()
all_ex_avai_bals = UserBalances.instance().all_avai_balances_all_exchanges()
Expand All @@ -88,18 +90,17 @@ async def show_balances(self):

for exchange, bals in all_ex_bals.items():
self._notify(f"\n{exchange}:")
# df = await self.exchange_balances_df(bals, all_ex_limits.get(exchange, {}))
df, allocated_total = await self.exchange_balances_usd_df(bals, all_ex_avai_bals.get(exchange, {}))
df, allocated_total = await self.exchange_balances_extra_df(bals, all_ex_avai_bals.get(exchange, {}))
if df.empty:
self._notify("You have no balance on this exchange.")
else:
lines = [" " + line for line in df.to_string(index=False).split("\n")]
self._notify("\n".join(lines))
self._notify(f"\n Total: $ {df['Total ($)'].sum():.0f} "
f"Allocated: {allocated_total / df['Total ($)'].sum():.2%}")
exchanges_total += df['Total ($)'].sum()
self._notify(f"\n Total: {RateOracle.global_token_symbol} {smart_round(df[total_col_name].sum())} "
f"Allocated: {allocated_total / df[total_col_name].sum():.2%}")
exchanges_total += df[total_col_name].sum()

self._notify(f"\n\nExchanges Total: $ {exchanges_total:.0f} ")
self._notify(f"\n\nExchanges Total: {RateOracle.global_token_symbol} {exchanges_total:.0f} ")

celo_address = global_config_map["celo_address"].value
if celo_address is not None:
Expand All @@ -126,41 +127,27 @@ async def show_balances(self):
self._notify("\nxdai:")
self._notify("\n".join(lines))

async def exchange_balances_df(self, # type: HummingbotApplication
exchange_balances: Dict[str, Decimal],
exchange_limits: Dict[str, str]):
rows = []
for token, bal in exchange_balances.items():
limit = Decimal(exchange_limits.get(token.upper(), 0)) if exchange_limits is not None else Decimal(0)
if bal == Decimal(0) and limit == Decimal(0):
continue
token = token.upper()
rows.append({"Asset": token.upper(),
"Amount": round(bal, 4),
"Limit": round(limit, 4) if limit > Decimal(0) else "-"})
df = pd.DataFrame(data=rows, columns=["Asset", "Amount", "Limit"])
df.sort_values(by=["Asset"], inplace=True)
return df

async def exchange_balances_usd_df(self, # type: HummingbotApplication
ex_balances: Dict[str, Decimal],
ex_avai_balances: Dict[str, Decimal]):
async def exchange_balances_extra_df(self, # type: HummingbotApplication
ex_balances: Dict[str, Decimal],
ex_avai_balances: Dict[str, Decimal]):
total_col_name = f"Total ({RateOracle.global_token_symbol})"
allocated_total = Decimal("0")
rows = []
for token, bal in ex_balances.items():
if bal == Decimal(0):
continue
avai = Decimal(ex_avai_balances.get(token.upper(), 0)) if ex_avai_balances is not None else Decimal(0)
allocated = f"{(bal - avai) / bal:.0%}"
usd = await usd_value(token, bal)
usd = 0 if usd is None else usd
allocated_total += await usd_value(token, (bal - avai))
rate = await RateOracle.global_rate(token)
rate = Decimal("0") if rate is None else rate
global_value = rate * bal
allocated_total += rate * (bal - avai)
rows.append({"Asset": token.upper(),
"Total": round(bal, 4),
"Total ($)": round(usd),
total_col_name: smart_round(global_value),
"Allocated": allocated,
})
df = pd.DataFrame(data=rows, columns=["Asset", "Total", "Total ($)", "Allocated"])
df = pd.DataFrame(data=rows, columns=["Asset", "Total", total_col_name, "Allocated"])
df.sort_values(by=["Asset"], inplace=True)
return df, allocated_total

Expand Down
13 changes: 6 additions & 7 deletions hummingbot/client/command/config_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
no_restart_pmm_keys_in_percentage = ["bid_spread", "ask_spread", "order_level_spread", "inventory_target_base_pct"]
no_restart_pmm_keys = ["order_amount", "order_levels", "filled_order_delay", "inventory_skew_enabled", "inventory_range_multiplier"]
global_configs_to_display = ["0x_active_cancels",
"autofill_import",
"kill_switch_enabled",
"kill_switch_rate",
"telegram_enabled",
Expand All @@ -44,17 +45,15 @@
"send_error_logs",
"script_enabled",
"script_file_path",
"manual_gas_price",
"ethereum_chain_name",
"ethgasstation_gas_enabled",
"ethgasstation_api_key",
"ethgasstation_gas_level",
"ethgasstation_refresh_time",
"gateway_enabled",
"gateway_cert_passphrase",
"gateway_api_host",
"gateway_api_port",
"balancer_max_swaps"]
"balancer_max_swaps",
"rate_oracle_source",
"global_token",
"global_token_symbol"]


class ConfigCommand:
Expand Down Expand Up @@ -199,7 +198,7 @@ async def asset_ratio_maintenance_prompt(self, # type: HummingbotApplication
balances = await UserBalances.instance().balances(exchange, base, quote)
if balances is None:
return
base_ratio = UserBalances.base_amount_ratio(exchange, market, balances)
base_ratio = await UserBalances.base_amount_ratio(exchange, market, balances)
if base_ratio is None:
return
base_ratio = round(base_ratio, 3)
Expand Down
5 changes: 3 additions & 2 deletions hummingbot/client/command/create_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ async def prompt_a_config(self, # type: HummingbotApplication
if input_value is None:
if assign_default:
self.app.set_text(parse_config_default_to_text(config))
input_value = await self.app.prompt(prompt=config.prompt, is_password=config.is_secure)
prompt = await config.get_prompt()
input_value = await self.app.prompt(prompt=prompt, is_password=config.is_secure)

if self.app.to_stop_config:
return
err_msg = config.validate(input_value)
err_msg = await config.validate(input_value)
if err_msg is not None:
self._notify(err_msg)
await self.prompt_a_config(config)
Expand Down
6 changes: 5 additions & 1 deletion hummingbot/client/command/import_command.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os

from hummingbot.core.utils.async_utils import safe_ensure_future
from hummingbot.client.config.global_config_map import global_config_map
from hummingbot.client.config.config_helpers import (
update_strategy_config_map_from_file,
short_strategy_name,
Expand Down Expand Up @@ -34,7 +35,7 @@ async def import_config_file(self, # type: HummingbotApplication
self.app.to_stop_config = False
return
strategy_path = os.path.join(CONF_FILE_PATH, file_name)
strategy = update_strategy_config_map_from_file(strategy_path)
strategy = await update_strategy_config_map_from_file(strategy_path)
self.strategy_file_name = file_name
self.strategy_name = strategy
self._notify(f"Configuration from {self.strategy_file_name} file is imported.")
Expand All @@ -43,6 +44,9 @@ async def import_config_file(self, # type: HummingbotApplication
self.app.change_prompt(prompt=">>> ")
if await self.status_check_all():
self._notify("\nEnter \"start\" to start market making.")
autofill_import = global_config_map.get("autofill_import").value
if autofill_import is not None:
self.app.set_text(autofill_import)

async def prompt_a_file_name(self # type: HummingbotApplication
):
Expand Down
16 changes: 9 additions & 7 deletions hummingbot/client/command/open_orders_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from datetime import timezone
from hummingbot.core.utils.async_utils import safe_ensure_future
from hummingbot.core.data_type.common import OpenOrder
from hummingbot.core.utils.market_price import usd_value, get_binance_mid_price
from hummingbot.core.utils.market_price import get_binance_mid_price
from hummingbot.core.rate_oracle.rate_oracle import RateOracle

s_float_0 = float(0)
s_decimal_0 = Decimal("0")
Expand All @@ -30,6 +31,7 @@ async def open_orders_report(self, # type: HummingbotApplication
full_report: bool):
exchange = "binance"
connector = await self.get_binance_connector()
g_sym = RateOracle.global_token_symbol
if connector is None:
self._notify("This command supports only binance (for now), please first connect to binance.")
return
Expand All @@ -39,31 +41,31 @@ async def open_orders_report(self, # type: HummingbotApplication
return
orders = sorted(orders, key=lambda x: (x.trading_pair, x.is_buy))
data = []
columns = ["Market", " Side", " Spread", " Size ($)", " Age"]
columns = ["Market", " Side", " Spread", f" Size ({g_sym})", " Age"]
if full_report:
columns.extend([" Allocation", " Per Total"])
cur_balances = await self.get_current_balances(exchange)
total_value = 0
for o in orders:
total_value += await usd_value(o.trading_pair.split("-")[0], o.amount)
total_value += await RateOracle.global_value(o.trading_pair.split("-")[0], o.amount)
for order in orders:
base, quote = order.trading_pair.split("-")
side = "buy" if order.is_buy else "sell"
mid_price = await get_binance_mid_price(order.trading_pair)
spread = abs(order.price - mid_price) / mid_price
size_usd = await usd_value(order.trading_pair.split("-")[0], order.amount)
size_global = await RateOracle.global_value(order.trading_pair.split("-")[0], order.amount)
age = pd.Timestamp((datetime.utcnow().replace(tzinfo=timezone.utc).timestamp() * 1e3 - order.time) / 1e3,
unit='s').strftime('%H:%M:%S')
data_row = [order.trading_pair, side, f"{spread:.2%}", round(size_usd), age]
data_row = [order.trading_pair, side, f"{spread:.2%}", round(size_global), age]
if full_report:
token = quote if order.is_buy else base
token_value = order.amount * order.price if order.is_buy else order.amount
per_bal = token_value / cur_balances[token]
token_txt = f"({token})"
data_row.extend([f"{per_bal:.0%} {token_txt:>6}", f"{size_usd / total_value:.0%}"])
data_row.extend([f"{per_bal:.0%} {token_txt:>6}", f"{size_global / total_value:.0%}"])
data.append(data_row)
lines = []
orders_df: pd.DataFrame = pd.DataFrame(data=data, columns=columns)
lines.extend([" " + line for line in orders_df.to_string(index=False).split("\n")])
self._notify("\n" + "\n".join(lines))
self._notify(f"\n Total: $ {total_value:.0f}")
self._notify(f"\n Total: {g_sym} {total_value:.0f}")
Loading

0 comments on commit 21b4a4e

Please sign in to comment.