Merge pull request #6423 from samgermain/wallet-amt

Futures wallet amount
This commit is contained in:
Matthias
2022-02-26 15:55:28 +01:00
committed by GitHub
13 changed files with 372 additions and 53 deletions

View File

@@ -1547,6 +1547,27 @@ def test_get_balances_prod(default_conf, mocker, exchange_name):
"get_balances", "fetch_balance")
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_fetch_positions(default_conf, mocker, exchange_name):
mocker.patch('freqtrade.exchange.Exchange.validate_trading_mode_and_margin_mode')
api_mock = MagicMock()
api_mock.fetch_positions = MagicMock(return_value=[
{'symbol': 'ETH/USDT:USDT', 'leverage': 5},
{'symbol': 'XRP/USDT:USDT', 'leverage': 5},
])
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
assert exchange.fetch_positions() == []
default_conf['dry_run'] = False
default_conf['trading_mode'] = 'futures'
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
res = exchange.fetch_positions()
assert len(res) == 2
ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name,
"fetch_positions", "fetch_positions")
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_get_tickers(default_conf, mocker, exchange_name):
api_mock = MagicMock()

View File

@@ -603,6 +603,30 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
'used': 5.0,
}
}
mock_pos = [
{
"symbol": "ETH/USDT:USDT",
"timestamp": None,
"datetime": None,
"initialMargin": 0.0,
"initialMarginPercentage": None,
"maintenanceMargin": 0.0,
"maintenanceMarginPercentage": 0.005,
"entryPrice": 0.0,
"notional": 100.0,
"leverage": 5.0,
"unrealizedPnl": 0.0,
"contracts": 100.0,
"contractSize": 1,
"marginRatio": None,
"liquidationPrice": 0.0,
"markPrice": 2896.41,
"collateral": 20,
"marginType": "isolated",
"side": 'short',
"percentage": None
}
]
mocker.patch.multiple(
'freqtrade.rpc.fiat_convert.CoinGeckoAPI',
@@ -612,12 +636,15 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_trading_mode_and_margin_mode=MagicMock(),
get_balances=MagicMock(return_value=mock_balance),
fetch_positions=MagicMock(return_value=mock_pos),
get_tickers=tickers,
get_valid_pair_combination=MagicMock(
side_effect=lambda a, b: f"{b}/{a}" if a == "USDT" else f"{a}/{b}")
)
default_conf['dry_run'] = False
default_conf['trading_mode'] = 'futures'
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot)
rpc = RPC(freqtradebot)
@@ -630,28 +657,55 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
assert tickers.call_args_list[0][1]['cached'] is True
assert 'USD' == result['symbol']
assert result['currencies'] == [
{'currency': 'BTC',
'free': 10.0,
'balance': 12.0,
'used': 2.0,
'est_stake': 12.0,
'stake': 'BTC',
},
{'free': 1.0,
'balance': 5.0,
'currency': 'ETH',
'est_stake': 0.30794,
'used': 4.0,
'stake': 'BTC',
{
'currency': 'BTC',
'free': 10.0,
'balance': 12.0,
'used': 2.0,
'est_stake': 12.0,
'stake': 'BTC',
'is_position': False,
'leverage': 1.0,
'position': 0.0,
'side': 'long',
},
{
'free': 1.0,
'balance': 5.0,
'currency': 'ETH',
'est_stake': 0.30794,
'used': 4.0,
'stake': 'BTC',
'is_position': False,
'leverage': 1.0,
'position': 0.0,
'side': 'long',
},
{'free': 5.0,
'balance': 10.0,
'currency': 'USDT',
'est_stake': 0.0011563153318162476,
'used': 5.0,
'stake': 'BTC',
}
},
{
'free': 5.0,
'balance': 10.0,
'currency': 'USDT',
'est_stake': 0.0011563153318162476,
'used': 5.0,
'stake': 'BTC',
'is_position': False,
'leverage': 1.0,
'position': 0.0,
'side': 'long',
},
{
'free': 0.0,
'balance': 0.0,
'currency': 'ETH/USDT:USDT',
'est_stake': 20,
'used': 0,
'stake': 'BTC',
'is_position': True,
'leverage': 5.0,
'position': 1000.0,
'side': 'short',
}
]
assert result['total'] == 12.309096315331816

View File

@@ -453,6 +453,10 @@ def test_api_balance(botclient, mocker, rpc_balance, tickers):
'used': 0.0,
'est_stake': 12.0,
'stake': 'BTC',
'is_position': False,
'leverage': 1.0,
'position': 0.0,
'side': 'long',
}
assert 'starting_capital' in response
assert 'starting_capital_fiat' in response

View File

@@ -905,6 +905,10 @@ def test_balance_handle_too_large_response(default_conf, update, mocker) -> None
'balance': i,
'est_stake': 1,
'stake': 'BTC',
'is_position': False,
'leverage': 1.0,
'position': 0.0,
'side': 'long',
})
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_balance', return_value={
'currencies': balances,

View File

@@ -95,6 +95,7 @@ def test_enter_exit_side(fee, is_short):
)
assert trade.enter_side == enter_side
assert trade.exit_side == exit_side
assert trade.trade_direction == 'short' if is_short else 'long'
@pytest.mark.usefixtures("init_persistence")

View File

@@ -6,7 +6,7 @@ import pytest
from freqtrade.constants import UNLIMITED_STAKE_AMOUNT
from freqtrade.exceptions import DependencyException
from tests.conftest import get_patched_freqtradebot, patch_wallet
from tests.conftest import create_mock_trades, get_patched_freqtradebot, patch_wallet
def test_sync_wallet_at_boot(mocker, default_conf):
@@ -234,3 +234,125 @@ def test_get_starting_balance(mocker, default_conf, available_capital, closed_pr
freqtrade = get_patched_freqtradebot(mocker, default_conf)
assert freqtrade.wallets.get_starting_balance() == expected
def test_sync_wallet_futures_live(mocker, default_conf):
default_conf['dry_run'] = False
default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated'
mock_result = [
{
"symbol": "ETH/USDT:USDT",
"timestamp": None,
"datetime": None,
"initialMargin": 0.0,
"initialMarginPercentage": None,
"maintenanceMargin": 0.0,
"maintenanceMarginPercentage": 0.005,
"entryPrice": 0.0,
"notional": 100.0,
"leverage": 5.0,
"unrealizedPnl": 0.0,
"contracts": 100.0,
"contractSize": 1,
"marginRatio": None,
"liquidationPrice": 0.0,
"markPrice": 2896.41,
"collateral": 20,
"marginType": "isolated",
"side": 'short',
"percentage": None
},
{
"symbol": "ADA/USDT:USDT",
"timestamp": None,
"datetime": None,
"initialMargin": 0.0,
"initialMarginPercentage": None,
"maintenanceMargin": 0.0,
"maintenanceMarginPercentage": 0.005,
"entryPrice": 0.0,
"notional": 100.0,
"leverage": 5.0,
"unrealizedPnl": 0.0,
"contracts": 100.0,
"contractSize": 1,
"marginRatio": None,
"liquidationPrice": 0.0,
"markPrice": 0.91,
"collateral": 20,
"marginType": "isolated",
"side": 'short',
"percentage": None
},
{
# Closed position
"symbol": "SOL/BUSD:BUSD",
"timestamp": None,
"datetime": None,
"initialMargin": 0.0,
"initialMarginPercentage": None,
"maintenanceMargin": 0.0,
"maintenanceMarginPercentage": 0.005,
"entryPrice": 0.0,
"notional": 0.0,
"leverage": 5.0,
"unrealizedPnl": 0.0,
"contracts": 0.0,
"contractSize": 1,
"marginRatio": None,
"liquidationPrice": 0.0,
"markPrice": 15.41,
"collateral": 0.0,
"marginType": "isolated",
"side": 'short',
"percentage": None
}
]
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value={
"USDT": {
"free": 900,
"used": 100,
"total": 1000
},
}),
fetch_positions=MagicMock(return_value=mock_result)
)
freqtrade = get_patched_freqtradebot(mocker, default_conf)
assert len(freqtrade.wallets._wallets) == 1
assert len(freqtrade.wallets._positions) == 2
assert 'USDT' in freqtrade.wallets._wallets
assert 'ETH/USDT:USDT' in freqtrade.wallets._positions
assert freqtrade.wallets._last_wallet_refresh > 0
# Remove ETH/USDT:USDT position
del mock_result[0]
freqtrade.wallets.update()
assert len(freqtrade.wallets._positions) == 1
assert 'ETH/USDT:USDT' not in freqtrade.wallets._positions
def test_sync_wallet_futures_dry(mocker, default_conf, fee):
default_conf['dry_run'] = True
default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated'
freqtrade = get_patched_freqtradebot(mocker, default_conf)
assert len(freqtrade.wallets._wallets) == 1
assert len(freqtrade.wallets._positions) == 0
create_mock_trades(fee, is_short=None)
freqtrade.wallets.update()
assert len(freqtrade.wallets._wallets) == 1
assert len(freqtrade.wallets._positions) == 4
positions = freqtrade.wallets.get_all_positions()
positions['ETH/BTC'].side == 'short'
positions['ETC/BTC'].side == 'long'
positions['XRP/BTC'].side == 'long'
positions['LTC/BTC'].side == 'short'