Merge pull request #8537 from freqtrade/feat/balance_improve
Improve balance output
This commit is contained in:
@@ -191,7 +191,8 @@ official commands. You can ask at any moment for help with `/help`.
|
|||||||
| **Metrics** |
|
| **Metrics** |
|
||||||
| `/profit [<n>]` | Display a summary of your profit/loss from close trades and some stats about your performance, over the last n days (all trades by default)
|
| `/profit [<n>]` | Display a summary of your profit/loss from close trades and some stats about your performance, over the last n days (all trades by default)
|
||||||
| `/performance` | Show performance of each finished trade grouped by pair
|
| `/performance` | Show performance of each finished trade grouped by pair
|
||||||
| `/balance` | Show account balance per currency
|
| `/balance` | Show bot managed balance per currency
|
||||||
|
| `/balance full` | Show account balance per currency
|
||||||
| `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7)
|
| `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7)
|
||||||
| `/weekly <n>` | Shows profit or loss per week, over the last n weeks (n defaults to 8)
|
| `/weekly <n>` | Shows profit or loss per week, over the last n weeks (n defaults to 8)
|
||||||
| `/monthly <n>` | Shows profit or loss per month, over the last n months (n defaults to 6)
|
| `/monthly <n>` | Shows profit or loss per month, over the last n months (n defaults to 6)
|
||||||
@@ -202,7 +203,6 @@ official commands. You can ask at any moment for help with `/help`.
|
|||||||
| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
|
| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
|
||||||
| `/edge` | Show validated pairs by Edge if it is enabled.
|
| `/edge` | Show validated pairs by Edge if it is enabled.
|
||||||
|
|
||||||
|
|
||||||
## Telegram commands in action
|
## Telegram commands in action
|
||||||
|
|
||||||
Below, example of Telegram message you will receive for each command.
|
Below, example of Telegram message you will receive for each command.
|
||||||
|
|||||||
@@ -36,20 +36,25 @@ class Balance(BaseModel):
|
|||||||
free: float
|
free: float
|
||||||
balance: float
|
balance: float
|
||||||
used: float
|
used: float
|
||||||
|
bot_owned: Optional[float]
|
||||||
est_stake: float
|
est_stake: float
|
||||||
|
est_stake_bot: Optional[float]
|
||||||
stake: str
|
stake: str
|
||||||
# Starting with 2.x
|
# Starting with 2.x
|
||||||
side: str
|
side: str
|
||||||
leverage: float
|
leverage: float
|
||||||
is_position: bool
|
is_position: bool
|
||||||
position: float
|
position: float
|
||||||
|
is_bot_managed: bool
|
||||||
|
|
||||||
|
|
||||||
class Balances(BaseModel):
|
class Balances(BaseModel):
|
||||||
currencies: List[Balance]
|
currencies: List[Balance]
|
||||||
total: float
|
total: float
|
||||||
|
total_bot: float
|
||||||
symbol: str
|
symbol: str
|
||||||
value: float
|
value: float
|
||||||
|
value_bot: float
|
||||||
stake: str
|
stake: str
|
||||||
note: str
|
note: str
|
||||||
starting_capital: float
|
starting_capital: float
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ logger = logging.getLogger(__name__)
|
|||||||
# 2.23: Allow plot config request in webserver mode
|
# 2.23: Allow plot config request in webserver mode
|
||||||
# 2.24: Add cancel_open_order endpoint
|
# 2.24: Add cancel_open_order endpoint
|
||||||
# 2.25: Add several profit values to /status endpoint
|
# 2.25: Add several profit values to /status endpoint
|
||||||
API_VERSION = 2.25
|
# 2.26: increase /balance output
|
||||||
|
API_VERSION = 2.26
|
||||||
|
|
||||||
# Public API, requires no auth.
|
# Public API, requires no auth.
|
||||||
router_public = APIRouter()
|
router_public = APIRouter()
|
||||||
|
|||||||
+27
-6
@@ -583,13 +583,16 @@ class RPC:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def __balance_get_est_stake(
|
def __balance_get_est_stake(
|
||||||
self, coin: str, stake_currency: str, balance: Wallet, tickers) -> float:
|
self, coin: str, stake_currency: str, amount: float,
|
||||||
|
balance: Wallet, tickers) -> Tuple[float, float]:
|
||||||
est_stake = 0.0
|
est_stake = 0.0
|
||||||
|
est_bot_stake = 0.0
|
||||||
if coin == stake_currency:
|
if coin == stake_currency:
|
||||||
est_stake = balance.total
|
est_stake = balance.total
|
||||||
if self._config.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT:
|
if self._config.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT:
|
||||||
# in Futures, "total" includes the locked stake, and therefore all positions
|
# in Futures, "total" includes the locked stake, and therefore all positions
|
||||||
est_stake = balance.free
|
est_stake = balance.free
|
||||||
|
est_bot_stake = amount
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
pair = self._freqtrade.exchange.get_valid_pair_combination(coin, stake_currency)
|
pair = self._freqtrade.exchange.get_valid_pair_combination(coin, stake_currency)
|
||||||
@@ -598,11 +601,12 @@ class RPC:
|
|||||||
if pair.startswith(stake_currency) and not pair.endswith(stake_currency):
|
if pair.startswith(stake_currency) and not pair.endswith(stake_currency):
|
||||||
rate = 1.0 / rate
|
rate = 1.0 / rate
|
||||||
est_stake = rate * balance.total
|
est_stake = rate * balance.total
|
||||||
|
est_bot_stake = rate * amount
|
||||||
except (ExchangeError):
|
except (ExchangeError):
|
||||||
logger.warning(f"Could not get rate for pair {coin}.")
|
logger.warning(f"Could not get rate for pair {coin}.")
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
return est_stake
|
return est_stake, est_bot_stake
|
||||||
|
|
||||||
def _rpc_balance(self, stake_currency: str, fiat_display_currency: str) -> Dict:
|
def _rpc_balance(self, stake_currency: str, fiat_display_currency: str) -> Dict:
|
||||||
""" Returns current account balance per crypto """
|
""" Returns current account balance per crypto """
|
||||||
@@ -615,7 +619,7 @@ class RPC:
|
|||||||
raise RPCException('Error getting current tickers.')
|
raise RPCException('Error getting current tickers.')
|
||||||
|
|
||||||
open_trades: List[Trade] = Trade.get_open_trades()
|
open_trades: List[Trade] = Trade.get_open_trades()
|
||||||
open_assets = [t.base_currency for t in open_trades]
|
open_assets: Dict[str, Trade] = {t.safe_base_currency: t for t in open_trades}
|
||||||
self._freqtrade.wallets.update(require_update=False)
|
self._freqtrade.wallets.update(require_update=False)
|
||||||
starting_capital = self._freqtrade.wallets.get_starting_balance()
|
starting_capital = self._freqtrade.wallets.get_starting_balance()
|
||||||
starting_cap_fiat = self._fiat_converter.convert_amount(
|
starting_cap_fiat = self._fiat_converter.convert_amount(
|
||||||
@@ -625,30 +629,43 @@ class RPC:
|
|||||||
for coin, balance in self._freqtrade.wallets.get_all_balances().items():
|
for coin, balance in self._freqtrade.wallets.get_all_balances().items():
|
||||||
if not balance.total:
|
if not balance.total:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
trade = open_assets.get(coin, None)
|
||||||
|
is_bot_managed = coin == stake_currency or trade is not None
|
||||||
|
trade_amount = trade.amount if trade else 0
|
||||||
|
if coin == stake_currency:
|
||||||
|
trade_amount = self._freqtrade.wallets.get_available_stake_amount()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
est_stake = self.__balance_get_est_stake(coin, stake_currency, balance, tickers)
|
est_stake, est_stake_bot = self.__balance_get_est_stake(
|
||||||
|
coin, stake_currency, trade_amount, balance, tickers)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
total += est_stake
|
total += est_stake
|
||||||
if coin == stake_currency or coin in open_assets:
|
|
||||||
total_bot += est_stake
|
if is_bot_managed:
|
||||||
|
total_bot += est_stake_bot
|
||||||
currencies.append({
|
currencies.append({
|
||||||
'currency': coin,
|
'currency': coin,
|
||||||
'free': balance.free,
|
'free': balance.free,
|
||||||
'balance': balance.total,
|
'balance': balance.total,
|
||||||
'used': balance.used,
|
'used': balance.used,
|
||||||
|
'bot_owned': trade_amount,
|
||||||
'est_stake': est_stake or 0,
|
'est_stake': est_stake or 0,
|
||||||
|
'est_stake_bot': est_stake_bot if is_bot_managed else 0,
|
||||||
'stake': stake_currency,
|
'stake': stake_currency,
|
||||||
'side': 'long',
|
'side': 'long',
|
||||||
'leverage': 1,
|
'leverage': 1,
|
||||||
'position': 0,
|
'position': 0,
|
||||||
|
'is_bot_managed': is_bot_managed,
|
||||||
'is_position': False,
|
'is_position': False,
|
||||||
})
|
})
|
||||||
symbol: str
|
symbol: str
|
||||||
position: PositionWallet
|
position: PositionWallet
|
||||||
for symbol, position in self._freqtrade.wallets.get_all_positions().items():
|
for symbol, position in self._freqtrade.wallets.get_all_positions().items():
|
||||||
total += position.collateral
|
total += position.collateral
|
||||||
|
total_bot += position.collateral
|
||||||
|
|
||||||
currencies.append({
|
currencies.append({
|
||||||
'currency': symbol,
|
'currency': symbol,
|
||||||
@@ -657,9 +674,11 @@ class RPC:
|
|||||||
'used': 0,
|
'used': 0,
|
||||||
'position': position.position,
|
'position': position.position,
|
||||||
'est_stake': position.collateral,
|
'est_stake': position.collateral,
|
||||||
|
'est_stake_bot': position.collateral,
|
||||||
'stake': stake_currency,
|
'stake': stake_currency,
|
||||||
'leverage': position.leverage,
|
'leverage': position.leverage,
|
||||||
'side': position.side,
|
'side': position.side,
|
||||||
|
'is_bot_managed': True,
|
||||||
'is_position': True
|
'is_position': True
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -675,8 +694,10 @@ class RPC:
|
|||||||
return {
|
return {
|
||||||
'currencies': currencies,
|
'currencies': currencies,
|
||||||
'total': total,
|
'total': total,
|
||||||
|
'total_bot': total_bot,
|
||||||
'symbol': fiat_display_currency,
|
'symbol': fiat_display_currency,
|
||||||
'value': value,
|
'value': value,
|
||||||
|
'value_bot': value_bot,
|
||||||
'stake': stake_currency,
|
'stake': stake_currency,
|
||||||
'starting_capital': starting_capital,
|
'starting_capital': starting_capital,
|
||||||
'starting_capital_ratio': starting_capital_ratio,
|
'starting_capital_ratio': starting_capital_ratio,
|
||||||
|
|||||||
+23
-14
@@ -905,6 +905,7 @@ class Telegram(RPCHandler):
|
|||||||
@authorized_only
|
@authorized_only
|
||||||
def _balance(self, update: Update, context: CallbackContext) -> None:
|
def _balance(self, update: Update, context: CallbackContext) -> None:
|
||||||
""" Handler for /balance """
|
""" Handler for /balance """
|
||||||
|
full_result = context.args and 'full' in context.args
|
||||||
result = self._rpc._rpc_balance(self._config['stake_currency'],
|
result = self._rpc._rpc_balance(self._config['stake_currency'],
|
||||||
self._config.get('fiat_display_currency', ''))
|
self._config.get('fiat_display_currency', ''))
|
||||||
|
|
||||||
@@ -915,8 +916,7 @@ class Telegram(RPCHandler):
|
|||||||
output = ''
|
output = ''
|
||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
output += "*Warning:* Simulated balances in Dry Mode.\n"
|
output += "*Warning:* Simulated balances in Dry Mode.\n"
|
||||||
starting_cap = round_coin_value(
|
starting_cap = round_coin_value(result['starting_capital'], self._config['stake_currency'])
|
||||||
result['starting_capital'], self._config['stake_currency'])
|
|
||||||
output += f"Starting capital: `{starting_cap}`"
|
output += f"Starting capital: `{starting_cap}`"
|
||||||
starting_cap_fiat = round_coin_value(
|
starting_cap_fiat = round_coin_value(
|
||||||
result['starting_capital_fiat'], self._config['fiat_display_currency']
|
result['starting_capital_fiat'], self._config['fiat_display_currency']
|
||||||
@@ -928,7 +928,10 @@ class Telegram(RPCHandler):
|
|||||||
total_dust_currencies = 0
|
total_dust_currencies = 0
|
||||||
for curr in result['currencies']:
|
for curr in result['currencies']:
|
||||||
curr_output = ''
|
curr_output = ''
|
||||||
if curr['est_stake'] > balance_dust_level:
|
if (
|
||||||
|
(curr['is_position'] or curr['est_stake'] > balance_dust_level)
|
||||||
|
and (full_result or curr['is_bot_managed'])
|
||||||
|
):
|
||||||
if curr['is_position']:
|
if curr['is_position']:
|
||||||
curr_output = (
|
curr_output = (
|
||||||
f"*{curr['currency']}:*\n"
|
f"*{curr['currency']}:*\n"
|
||||||
@@ -937,13 +940,17 @@ class Telegram(RPCHandler):
|
|||||||
f"\t`Est. {curr['stake']}: "
|
f"\t`Est. {curr['stake']}: "
|
||||||
f"{round_coin_value(curr['est_stake'], curr['stake'], False)}`\n")
|
f"{round_coin_value(curr['est_stake'], curr['stake'], False)}`\n")
|
||||||
else:
|
else:
|
||||||
|
est_stake = round_coin_value(
|
||||||
|
curr['est_stake' if full_result else 'est_stake_bot'], curr['stake'], False)
|
||||||
|
|
||||||
curr_output = (
|
curr_output = (
|
||||||
f"*{curr['currency']}:*\n"
|
f"*{curr['currency']}:*\n"
|
||||||
f"\t`Available: {curr['free']:.8f}`\n"
|
f"\t`Available: {curr['free']:.8f}`\n"
|
||||||
f"\t`Balance: {curr['balance']:.8f}`\n"
|
f"\t`Balance: {curr['balance']:.8f}`\n"
|
||||||
f"\t`Pending: {curr['used']:.8f}`\n"
|
f"\t`Pending: {curr['used']:.8f}`\n"
|
||||||
f"\t`Est. {curr['stake']}: "
|
f"\t`Bot Owned: {curr['bot_owned']:.8f}`\n"
|
||||||
f"{round_coin_value(curr['est_stake'], curr['stake'], False)}`\n")
|
f"\t`Est. {curr['stake']}: {est_stake}`\n")
|
||||||
|
|
||||||
elif curr['est_stake'] <= balance_dust_level:
|
elif curr['est_stake'] <= balance_dust_level:
|
||||||
total_dust_balance += curr['est_stake']
|
total_dust_balance += curr['est_stake']
|
||||||
total_dust_currencies += 1
|
total_dust_currencies += 1
|
||||||
@@ -965,14 +972,15 @@ class Telegram(RPCHandler):
|
|||||||
tc = result['trade_count'] > 0
|
tc = result['trade_count'] > 0
|
||||||
stake_improve = f" `({result['starting_capital_ratio']:.2%})`" if tc else ''
|
stake_improve = f" `({result['starting_capital_ratio']:.2%})`" if tc else ''
|
||||||
fiat_val = f" `({result['starting_capital_fiat_ratio']:.2%})`" if tc else ''
|
fiat_val = f" `({result['starting_capital_fiat_ratio']:.2%})`" if tc else ''
|
||||||
|
value = round_coin_value(
|
||||||
output += ("\n*Estimated Value*:\n"
|
result['value' if full_result else 'value_bot'], result['symbol'], False)
|
||||||
f"\t`{result['stake']}: "
|
total_stake = round_coin_value(
|
||||||
f"{round_coin_value(result['total'], result['stake'], False)}`"
|
result['total' if full_result else 'total_bot'], result['stake'], False)
|
||||||
f"{stake_improve}\n"
|
output += (
|
||||||
f"\t`{result['symbol']}: "
|
f"\n*Estimated Value{' (Bot managed assets only)' if not full_result else ''}*:\n"
|
||||||
f"{round_coin_value(result['value'], result['symbol'], False)}`"
|
f"\t`{result['stake']}: {total_stake}`{stake_improve}\n"
|
||||||
f"{fiat_val}\n")
|
f"\t`{result['symbol']}: {value}`{fiat_val}\n"
|
||||||
|
)
|
||||||
self._send_msg(output, reload_able=True, callback_path="update_balance",
|
self._send_msg(output, reload_able=True, callback_path="update_balance",
|
||||||
query=update.callback_query)
|
query=update.callback_query)
|
||||||
|
|
||||||
@@ -1528,7 +1536,8 @@ class Telegram(RPCHandler):
|
|||||||
"------------\n"
|
"------------\n"
|
||||||
"*/show_config:* `Show running configuration` \n"
|
"*/show_config:* `Show running configuration` \n"
|
||||||
"*/locks:* `Show currently locked pairs`\n"
|
"*/locks:* `Show currently locked pairs`\n"
|
||||||
"*/balance:* `Show account balance per currency`\n"
|
"*/balance:* `Show bot managed balance per currency`\n"
|
||||||
|
"*/balance total:* `Show account balance per currency`\n"
|
||||||
"*/logs [limit]:* `Show latest logs - defaults to 10` \n"
|
"*/logs [limit]:* `Show latest logs - defaults to 10` \n"
|
||||||
"*/count:* `Show number of active trades compared to allowed number of trades`\n"
|
"*/count:* `Show number of active trades compared to allowed number of trades`\n"
|
||||||
"*/edge:* `Shows validated pairs by Edge if it is enabled` \n"
|
"*/edge:* `Shows validated pairs by Edge if it is enabled` \n"
|
||||||
|
|||||||
+16
-2
@@ -546,53 +546,67 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
|
|||||||
'free': 10.0,
|
'free': 10.0,
|
||||||
'balance': 12.0,
|
'balance': 12.0,
|
||||||
'used': 2.0,
|
'used': 2.0,
|
||||||
|
'bot_owned': 9.9, # available stake - reducing by reserved amount
|
||||||
'est_stake': 10.0, # In futures mode, "free" is used here.
|
'est_stake': 10.0, # In futures mode, "free" is used here.
|
||||||
|
'est_stake_bot': 9.9,
|
||||||
'stake': 'BTC',
|
'stake': 'BTC',
|
||||||
'is_position': False,
|
'is_position': False,
|
||||||
'leverage': 1.0,
|
'leverage': 1.0,
|
||||||
'position': 0.0,
|
'position': 0.0,
|
||||||
'side': 'long',
|
'side': 'long',
|
||||||
|
'is_bot_managed': True,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'free': 1.0,
|
'free': 1.0,
|
||||||
'balance': 5.0,
|
'balance': 5.0,
|
||||||
'currency': 'ETH',
|
'currency': 'ETH',
|
||||||
|
'bot_owned': 0,
|
||||||
'est_stake': 0.30794,
|
'est_stake': 0.30794,
|
||||||
|
'est_stake_bot': 0,
|
||||||
'used': 4.0,
|
'used': 4.0,
|
||||||
'stake': 'BTC',
|
'stake': 'BTC',
|
||||||
'is_position': False,
|
'is_position': False,
|
||||||
'leverage': 1.0,
|
'leverage': 1.0,
|
||||||
'position': 0.0,
|
'position': 0.0,
|
||||||
'side': 'long',
|
'side': 'long',
|
||||||
|
'is_bot_managed': False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'free': 5.0,
|
'free': 5.0,
|
||||||
'balance': 10.0,
|
'balance': 10.0,
|
||||||
'currency': 'USDT',
|
'currency': 'USDT',
|
||||||
|
'bot_owned': 0,
|
||||||
'est_stake': 0.0011562404610161968,
|
'est_stake': 0.0011562404610161968,
|
||||||
|
'est_stake_bot': 0,
|
||||||
'used': 5.0,
|
'used': 5.0,
|
||||||
'stake': 'BTC',
|
'stake': 'BTC',
|
||||||
'is_position': False,
|
'is_position': False,
|
||||||
'leverage': 1.0,
|
'leverage': 1.0,
|
||||||
'position': 0.0,
|
'position': 0.0,
|
||||||
'side': 'long',
|
'side': 'long',
|
||||||
|
'is_bot_managed': False,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'free': 0.0,
|
'free': 0.0,
|
||||||
'balance': 0.0,
|
'balance': 0.0,
|
||||||
'currency': 'ETH/USDT:USDT',
|
'currency': 'ETH/USDT:USDT',
|
||||||
'est_stake': 20,
|
'est_stake': 20,
|
||||||
|
'est_stake_bot': 20,
|
||||||
'used': 0,
|
'used': 0,
|
||||||
'stake': 'BTC',
|
'stake': 'BTC',
|
||||||
'is_position': True,
|
'is_position': True,
|
||||||
'leverage': 5.0,
|
'leverage': 5.0,
|
||||||
'position': 1000.0,
|
'position': 1000.0,
|
||||||
'side': 'short',
|
'side': 'short',
|
||||||
|
'is_bot_managed': True,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
assert pytest.approx(result['total_bot']) == 29.9
|
||||||
|
assert pytest.approx(result['total']) == 30.309096
|
||||||
assert result['starting_capital'] == 10
|
assert result['starting_capital'] == 10
|
||||||
assert result['starting_capital_ratio'] == 0.0
|
# Very high starting capital ratio, because the futures position really has the wrong unit.
|
||||||
|
# TODO: improve this test (see comment above)
|
||||||
|
assert result['starting_capital_ratio'] == pytest.approx(1.98999999)
|
||||||
|
|
||||||
|
|
||||||
def test_rpc_start(mocker, default_conf) -> None:
|
def test_rpc_start(mocker, default_conf) -> None:
|
||||||
|
|||||||
@@ -480,13 +480,18 @@ def test_api_balance(botclient, mocker, rpc_balance, tickers):
|
|||||||
'free': 12.0,
|
'free': 12.0,
|
||||||
'balance': 12.0,
|
'balance': 12.0,
|
||||||
'used': 0.0,
|
'used': 0.0,
|
||||||
|
'bot_owned': pytest.approx(11.879999),
|
||||||
'est_stake': 12.0,
|
'est_stake': 12.0,
|
||||||
|
'est_stake_bot': pytest.approx(11.879999),
|
||||||
'stake': 'BTC',
|
'stake': 'BTC',
|
||||||
'is_position': False,
|
'is_position': False,
|
||||||
'leverage': 1.0,
|
'leverage': 1.0,
|
||||||
'position': 0.0,
|
'position': 0.0,
|
||||||
'side': 'long',
|
'side': 'long',
|
||||||
|
'is_bot_managed': True,
|
||||||
}
|
}
|
||||||
|
assert response['total'] == 12.159513094
|
||||||
|
assert response['total_bot'] == pytest.approx(11.879999)
|
||||||
assert 'starting_capital' in response
|
assert 'starting_capital' in response
|
||||||
assert 'starting_capital_fiat' in response
|
assert 'starting_capital_fiat' in response
|
||||||
assert 'starting_capital_pct' in response
|
assert 'starting_capital_pct' in response
|
||||||
|
|||||||
@@ -783,19 +783,28 @@ def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance, tick
|
|||||||
patch_get_signal(freqtradebot)
|
patch_get_signal(freqtradebot)
|
||||||
|
|
||||||
telegram._balance(update=update, context=MagicMock())
|
telegram._balance(update=update, context=MagicMock())
|
||||||
|
context = MagicMock()
|
||||||
|
context.args = ["full"]
|
||||||
|
telegram._balance(update=update, context=context)
|
||||||
result = msg_mock.call_args_list[0][0][0]
|
result = msg_mock.call_args_list[0][0][0]
|
||||||
assert msg_mock.call_count == 1
|
result_full = msg_mock.call_args_list[1][0][0]
|
||||||
|
assert msg_mock.call_count == 2
|
||||||
assert '*BTC:*' in result
|
assert '*BTC:*' in result
|
||||||
assert '*ETH:*' not in result
|
assert '*ETH:*' not in result
|
||||||
assert '*USDT:*' not in result
|
assert '*USDT:*' not in result
|
||||||
assert '*EUR:*' not in result
|
assert '*EUR:*' not in result
|
||||||
assert '*LTC:*' in result
|
assert '*LTC:*' not in result
|
||||||
|
|
||||||
|
assert '*LTC:*' in result_full
|
||||||
assert '*XRP:*' not in result
|
assert '*XRP:*' not in result
|
||||||
assert 'Balance:' in result
|
assert 'Balance:' in result
|
||||||
assert 'Est. BTC:' in result
|
assert 'Est. BTC:' in result
|
||||||
assert 'BTC: 12' in result
|
assert 'BTC: 11' in result
|
||||||
|
assert 'BTC: 12' in result_full
|
||||||
assert "*3 Other Currencies (< 0.0001 BTC):*" in result
|
assert "*3 Other Currencies (< 0.0001 BTC):*" in result
|
||||||
assert 'BTC: 0.00000309' in result
|
assert 'BTC: 0.00000309' in result
|
||||||
|
assert '*Estimated Value*:' in result_full
|
||||||
|
assert '*Estimated Value (Bot managed assets only)*:' in result
|
||||||
|
|
||||||
|
|
||||||
def test_balance_handle_empty_response(default_conf, update, mocker) -> None:
|
def test_balance_handle_empty_response(default_conf, update, mocker) -> None:
|
||||||
@@ -834,18 +843,23 @@ def test_balance_handle_too_large_response(default_conf, update, mocker) -> None
|
|||||||
'free': 1.0,
|
'free': 1.0,
|
||||||
'used': 0.5,
|
'used': 0.5,
|
||||||
'balance': i,
|
'balance': i,
|
||||||
|
'bot_owned': 0.5,
|
||||||
'est_stake': 1,
|
'est_stake': 1,
|
||||||
|
'est_stake_bot': 1,
|
||||||
'stake': 'BTC',
|
'stake': 'BTC',
|
||||||
'is_position': False,
|
'is_position': False,
|
||||||
'leverage': 1.0,
|
'leverage': 1.0,
|
||||||
'position': 0.0,
|
'position': 0.0,
|
||||||
'side': 'long',
|
'side': 'long',
|
||||||
|
'is_bot_managed': True,
|
||||||
})
|
})
|
||||||
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_balance', return_value={
|
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_balance', return_value={
|
||||||
'currencies': balances,
|
'currencies': balances,
|
||||||
'total': 100.0,
|
'total': 100.0,
|
||||||
|
'total_bot': 100.0,
|
||||||
'symbol': 100.0,
|
'symbol': 100.0,
|
||||||
'value': 1000.0,
|
'value': 1000.0,
|
||||||
|
'value_bot': 1000.0,
|
||||||
'starting_capital': 1000,
|
'starting_capital': 1000,
|
||||||
'starting_capital_fiat': 1000,
|
'starting_capital_fiat': 1000,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user