Skip to content

Commit

Permalink
Merge pull request hummingbot#2936 from CoinAlpha/development
Browse files Browse the repository at this point in the history
release / sync dev 0.36.0 -> master (PR 3 of 3)
  • Loading branch information
dennisocana authored Feb 9, 2021
2 parents c314a9d + 7a2d6d2 commit 6362d1d
Show file tree
Hide file tree
Showing 115 changed files with 7,233 additions and 486 deletions.
36 changes: 20 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,28 @@ We created hummingbot to promote **decentralized market-making**: enabling membe

![RED](https://via.placeholder.com/15/f03c15/?text=+) RED - Connector is broken and unusable

OKEx is reportedly being investigated by Chinese authorities and has stopped withdrawals.

## Supported centralized exchanges

| logo | id | name | ver | doc | status |
|:---:|:---:|:---:|:---:|:---:|:---:|
| <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-exchange/binance-official-api-docs/blob/master/rest-api.md) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) | Connector is working properly
| <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) | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/blocktane_logo.png" alt="Blocktane" width="90" /> | blocktane | [Blocktane](https://blocktane.io/) | 2 | [API](https://blocktane.io/api) | ![YELLOW](https://via.placeholder.com/15/ffff00/?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" /> | dy/dx | [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/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/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/liquid_logo.png" alt="Liquid" width="90" /> | liquid | [Liquid](https://www.liquid.com/) | 2 | [API](https://developers.liquid.com/) | ![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) | ![YELLOW](https://via.placeholder.com/15/ffff00/?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/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/bitfinex_logo.png" alt="Bitfinex" width="90" /> | bitfinex | [Bitfinex](https://www.bitfinex.com/) | 2 | [API](https://docs.bitfinex.com/docs/introduction) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/okex_logo.png" alt="OKEx" width="90" /> | okex | [OKEx](https://www.okex.com/) | 2 | [API](https://www.okex.com/docs/en/) | ![RED](https://via.placeholder.com/15/f03c15/?text=+) |
| <img src="assets/dydx_logo.png" alt="DyDx" width="90" /> | dy/dx | [dy/dx](https://dydx.exchange/) | 1 | [API](https://docs.dydx.exchange/) | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/liquid_logo.png" alt="Liquid" width="90" /> | liquid | [Liquid](https://www.liquid.com/) | 2 | [API](https://developers.liquid.com/) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/okex_logo.png" alt="OKEx" width="90" /> | okex | [OKEx](https://www.okex.com/) | 3 | [API](https://www.okex.com/docs/en/) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |



## Supported decentralized exchanges
Expand All @@ -46,16 +50,16 @@ OKEx is reportedly being investigated by Chinese authorities and has stopped wit
| <img src="https://i.ibb.co/1sPt940/Screen-Shot-2019-06-06-at-17-50-04.png" alt="Bamboo Relay" width="90" /> | bamboo_relay | [Bamboo Relay](https://bamboorelay.com/) | 3 | [API](https://sra.bamboorelay.com/) | [[email protected]](mailto:[email protected]) | ![RED](https://via.placeholder.com/15/f03c15/?text=+) |
|<img src="assets/dolomite_logo.png" alt="Dolomite" width="90" />| dolomite | [Dolomite](https://dolomite.io/) | 1 | [API](https://docs.dolomite.io/) | [[email protected]](mailto:[email protected]) | ![RED](https://via.placeholder.com/15/f03c15/?text=+) |
| <img src="assets/radar_logo.png" alt="Radar Relay" width="90" height="30" /> | radar_relay | [Radar Relay](https://radarrelay.com/) | 2 | [API](https://developers.radarrelay.com/api/trade-api) | | ![unavailable](https://via.placeholder.com/15/f03c15/?text=+) |
| <img src="assets/loopring_logo.png" alt="Loopring" width="90" /> | loopring | [Loopring](https://loopring.io/) | * | [API](https://docs.loopring.io/en/) | | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/loopring_logo.png" alt="Loopring" width="90" /> | loopring | [Loopring](https://loopring.io/) | 3 | [API](https://docs3.loopring.io/en/) | | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |


## Supported protocol exchanges
| logo | id | name | ver | doc| status |
|:---:|:---:|:---:|:---:|:---:|:--:|
| <img src="assets/celo_logo.svg" alt="Celo" width="90" /> | celo | [Celo](https://celo.org/) | * | [SDK](https://celo.org/developers) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/balancer_logo.svg" alt="Balancer" width="90" height="30" /> | balancer | [Balancer](https://balancer.finance/) | * | [SDK](https://docs.balancer.finance/) | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/terra_logo.png" alt="Terra" width="90" /> | terra | [Terra](https://terra.money/) | * | [SDK](https://docs.terra.money/) | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/uniswap_logo.svg" alt="Uniswap" width="90" height="30" /> | uniswap | [Uniswap](https://uniswap.org/) | * | [SDK](https://uniswap.org/docs/v2/) | ![YELLOW](https://via.placeholder.com/15/ffff00/?text=+) |
| <img src="assets/celo_logo.svg" alt="Celo" width="90" /> | celo | [Celo](https://terra.money/) | * | [SDK](https://celo.org/developers) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/balancer_logo.svg" alt="Balancer" width="90" height="30" /> | balancer | [Balancer](https://balancer.finance/) | * | [SDK](https://docs.balancer.finance/) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/terra_logo.png" alt="Terra" width="90" /> | terra | [Terra](https://terra.money/) | * | [SDK](https://docs.terra.money/) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |
| <img src="assets/uniswap_logo.svg" alt="Uniswap" width="90" height="30" /> | uniswap | [Uniswap](https://uniswap.org/) | * | [SDK](https://uniswap.org/docs/v2/) | ![GREEN](https://via.placeholder.com/15/008000/?text=+) |



Expand All @@ -65,7 +69,7 @@ OKEx is reportedly being investigated by Chinese authorities and has stopped wit

- [Website](https://hummingbot.io)
- [Documentation](https://docs.hummingbot.io)
- [FAQs](https://docs.hummingbot.io/resources/faq/)
- [FAQs](https://hummingbot.zendesk.com/hc/en-us/categories/900001272063-Hummingbot-FAQs)

### Install Hummingbot

Expand Down Expand Up @@ -98,4 +102,4 @@ Hummingbot was created and is maintained by CoinAlpha, Inc. We are [a global tea
## Legal

- **License**: Hummingbot is licensed under [Apache 2.0](./LICENSE).
- **Data collection**: read important information regarding [Hummingbot Data Collection](DATA_COLLECTION.md).
- **Data collection**: read important information regarding [Hummingbot Data Collection](DATA_COLLECTION.md).
Binary file added assets/binance_perpetual_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 added assets/binanceus_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 added assets/bitmax_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 added assets/blocktane_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 hummingbot/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.35.0
0.36.0
58 changes: 55 additions & 3 deletions hummingbot/client/command/config_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@
from decimal import Decimal
import pandas as pd
from os.path import join
from sqlalchemy.orm import Session
from hummingbot.client.settings import (
GLOBAL_CONFIG_PATH,
CONF_FILE_PATH,
)
from hummingbot.client.config.global_config_map import global_config_map
from hummingbot.client.config.config_validators import validate_bool
from hummingbot.client.config.config_validators import validate_bool, validate_decimal
from hummingbot.client.config.config_helpers import (
missing_required_configs,
save_to_yml
)
from hummingbot.client.config.security import Security
from hummingbot.client.config.config_var import ConfigVar
from hummingbot.core.utils.async_utils import safe_ensure_future
from hummingbot.model.inventory_cost import InventoryCost
from hummingbot.strategy.pure_market_making import (
PureMarketMakingStrategy
)
Expand Down Expand Up @@ -76,14 +78,14 @@ def list_configs(self, # type: HummingbotApplication
if cv.key in global_configs_to_display and not cv.is_secure]
df = pd.DataFrame(data=data, columns=columns)
self._notify("\nGlobal Configurations:")
lines = [" " + line for line in df.to_string(index=False).split("\n")]
lines = [" " + line for line in df.to_string(index=False, max_colwidth=50).split("\n")]
self._notify("\n".join(lines))

if self.strategy_name is not None:
data = [[cv.key, cv.value] for cv in self.strategy_config_map.values() if not cv.is_secure]
df = pd.DataFrame(data=data, columns=columns)
self._notify("\nStrategy Configurations:")
lines = [" " + line for line in df.to_string(index=False).split("\n")]
lines = [" " + line for line in df.to_string(index=False, max_colwidth=50).split("\n")]
self._notify("\n".join(lines))

def config_able_keys(self # type: HummingbotApplication
Expand Down Expand Up @@ -141,6 +143,8 @@ async def _config_single_key(self, # type: HummingbotApplication
self._notify("Please follow the prompt to complete configurations: ")
if config_var.key == "inventory_target_base_pct":
await self.asset_ratio_maintenance_prompt(config_map, input_value)
elif config_var.key == "inventory_price":
await self.inventory_price_prompt(config_map, input_value)
else:
await self.prompt_a_config(config_var, input_value=input_value, assign_default=False)
if self.app.to_stop_config:
Expand Down Expand Up @@ -219,3 +223,51 @@ async def asset_ratio_maintenance_prompt(self, # type: HummingbotApplication
self.app.to_stop_config = False
return
await self.prompt_a_config(config_map["inventory_target_base_pct"])

async def inventory_price_prompt(
self, # type: HummingbotApplication
config_map,
input_value=None,
):
key = "inventory_price"
if input_value:
config_map[key].value = Decimal(input_value)
else:
exchange = config_map["exchange"].value
market = config_map["market"].value
base_asset, quote_asset = market.split("-")
balances = await UserBalances.instance().balances(
exchange, base_asset, quote_asset
)
if balances.get(base_asset) is None:
return

cvar = ConfigVar(
key="temp_config",
prompt=f"On {exchange}, you have {balances[base_asset]:.4f} {base_asset}. "
f"What was the price for this amount in {quote_asset}? >>> ",
required_if=lambda: True,
type_str="decimal",
validator=lambda v: validate_decimal(
v, min_value=Decimal("0"), inclusive=True
),
)
await self.prompt_a_config(cvar)
config_map[key].value = cvar.value

try:
quote_volume = balances[base_asset] * cvar.value
except TypeError:
# TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'NoneType' - bad input / no input
self._notify("Inventory price not updated due to bad input")
return

session: Session = self.trade_fill_db.get_shared_session()
InventoryCost.add_volume(
session,
base_asset=base_asset,
quote_asset=quote_asset,
base_volume=balances[base_asset],
quote_volume=quote_volume,
overwrite=True,
)
5 changes: 4 additions & 1 deletion hummingbot/client/command/history_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
from hummingbot.client.settings import (
MAXIMUM_TRADE_FILLS_DISPLAY_OUTPUT,
CONNECTOR_SETTINGS,
ConnectorType
ConnectorType,
DERIVATIVES
)
from hummingbot.model.trade_fill import TradeFill
from hummingbot.user.user_balances import UserBalances
Expand Down Expand Up @@ -141,6 +142,7 @@ def report_performance_by_market(self, # type: HummingbotApplication

assets_columns = ["", "start", "current", "change"]
assets_data = [
[f"{base:<17}", "-", "-", "-"] if market in DERIVATIVES else # No base asset for derivatives because they are margined
[f"{base:<17}",
smart_round(perf.start_base_bal, precision),
smart_round(perf.cur_base_bal, precision),
Expand All @@ -153,6 +155,7 @@ def report_performance_by_market(self, # type: HummingbotApplication
smart_round(perf.start_price),
smart_round(perf.cur_price),
smart_round(perf.cur_price - perf.start_price)],
[f"{'Base asset %':<17}", "-", "-", "-"] if market in DERIVATIVES else # No base asset for derivatives because they are margined
[f"{'Base asset %':<17}",
f"{perf.start_base_ratio_pct:.2%}",
f"{perf.cur_base_ratio_pct:.2%}",
Expand Down
5 changes: 4 additions & 1 deletion hummingbot/client/command/pnl_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ async def pnl_report(self, # type: HummingbotApplication
orders: List[OpenOrder] = await connector.get_open_orders()
markets = {o.trading_pair for o in orders}
else:
markets = set(global_config_map["binance_markets"].value.split(","))
if self.strategy_config_map is not None and "markets" in self.strategy_config_map:
markets = set(self.strategy_config_map["markets"].value.split(","))
else:
markets = set(global_config_map["binance_markets"].value.split(","))
markets = sorted(markets)
data = []
columns = ["Market", " Traded ($)", " Fee ($)", " PnL ($)", " Return %"]
Expand Down
8 changes: 5 additions & 3 deletions hummingbot/client/command/start_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ async def start_check(self, # type: HummingbotApplication
if not is_valid:
return

init_logging("hummingbot_logs.yml",
override_log_level=log_level.upper() if log_level else None,
strategy_file_path=self.strategy_file_name)
if self._last_started_strategy_file != self.strategy_file_name:
init_logging("hummingbot_logs.yml",
override_log_level=log_level.upper() if log_level else None,
strategy_file_path=self.strategy_file_name)
self._last_started_strategy_file = self.strategy_file_name

# If macOS, disable App Nap.
if platform.system() == "Darwin":
Expand Down
14 changes: 7 additions & 7 deletions hummingbot/client/config/config_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,24 @@ def validate_bool(value: str) -> Optional[str]:
return f"Invalid value, please choose value from {valid_values}"


def validate_int(value: str, min_value: Decimal = None, max_value: Decimal = None, inclusive=True) -> Optional[str]:
def validate_int(value: str, min_value: int = None, max_value: int = None, inclusive=True) -> Optional[str]:
try:
int_value = int(value)
except Exception:
return f"{value} is not in integer format."
if inclusive:
if min_value is not None and max_value is not None:
if not (int(str(min_value)) <= int_value <= int(str(max_value))):
if not (min_value <= int_value <= max_value):
return f"Value must be between {min_value} and {max_value}."
elif min_value is not None and not int_value >= int(str(min_value)):
elif min_value is not None and not int_value >= min_value:
return f"Value cannot be less than {min_value}."
elif max_value is not None and not int_value <= int(str(max_value)):
elif max_value is not None and not int_value <= max_value:
return f"Value cannot be more than {max_value}."
else:
if min_value is not None and max_value is not None:
if not (int(str(min_value)) < int_value < int(str(max_value))):
if not (min_value < int_value < max_value):
return f"Value must be between {min_value} and {max_value} (exclusive)."
elif min_value is not None and not int_value > int(str(min_value)):
elif min_value is not None and not int_value > min_value:
return f"Value must be more than {min_value}."
elif max_value is not None and not int_value < int(str(max_value)):
elif max_value is not None and not int_value < max_value:
return f"Value must be less than {max_value}."
1 change: 1 addition & 0 deletions hummingbot/client/hummingbot_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def __init__(self):
self.kill_switch: Optional[KillSwitch] = None
self._app_warnings: Deque[ApplicationWarning] = deque()
self._trading_required: bool = True
self._last_started_strategy_file: Optional[str] = None

self.trade_fill_db: Optional[SQLConnectionManager] = None
self.markets_recorder: Optional[MarketsRecorder] = None
Expand Down
Loading

0 comments on commit 6362d1d

Please sign in to comment.