Merge branch 'lev-exchange' into lev-freqtradebot

This commit is contained in:
Sam Germain 2021-09-10 23:59:45 -06:00
commit 02521b4010
6 changed files with 51 additions and 38 deletions

View File

@ -41,8 +41,8 @@ class Binance(Exchange):
""" """
return order['type'] == 'stop_loss_limit' and ( return order['type'] == 'stop_loss_limit' and (
side == "sell" and stop_loss > float(order['info']['stopPrice']) or (side == "sell" and stop_loss > float(order['info']['stopPrice'])) or
side == "buy" and stop_loss < float(order['info']['stopPrice']) (side == "buy" and stop_loss < float(order['info']['stopPrice']))
) )
@retrier(retries=0) @retrier(retries=0)
@ -55,11 +55,12 @@ class Binance(Exchange):
:param side: "buy" or "sell" :param side: "buy" or "sell"
""" """
# Limit price threshold: As limit price should always be below stop-price # Limit price threshold: As limit price should always be below stop-price
limit_price_pct = order_types.get( limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
'stoploss_on_exchange_limit_ratio', if side == "sell":
0.99 if side == 'sell' else 1.01 # TODO: Name limit_rate in other exchange subclasses
) rate = stop_price * limit_price_pct
rate = stop_price * limit_price_pct else:
rate = stop_price * (2 - limit_price_pct)
ordertype = "stop_loss_limit" ordertype = "stop_loss_limit"

View File

@ -1597,8 +1597,7 @@ class Exchange:
:param pair: The base/quote currency pair being traded :param pair: The base/quote currency pair being traded
:nominal_value: The total value of the trade in quote currency (collateral + debt) :nominal_value: The total value of the trade in quote currency (collateral + debt)
""" """
raise OperationalException( return 1.0
f"{self.name.capitalize()}.get_max_leverage has not been implemented.")
@retrier @retrier
def set_leverage(self, leverage: float, pair: Optional[str]): def set_leverage(self, leverage: float, pair: Optional[str]):
@ -1606,6 +1605,10 @@ class Exchange:
Set's the leverage before making a trade, in order to not Set's the leverage before making a trade, in order to not
have the same leverage on every trade have the same leverage on every trade
""" """
if not self.exchange_has("setLeverage"):
# Some exchanges only support one collateral type
return
try: try:
self._api.set_leverage(symbol=pair, leverage=leverage) self._api.set_leverage(symbol=pair, leverage=leverage)
except ccxt.DDoSProtection as e: except ccxt.DDoSProtection as e:

View File

@ -57,11 +57,11 @@ class Ftx(Exchange):
Limit orders are defined by having orderPrice set, otherwise a market order is used. Limit orders are defined by having orderPrice set, otherwise a market order is used.
""" """
limit_price_pct = order_types.get( limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
'stoploss_on_exchange_limit_ratio', if side == "sell":
0.99 if side == "sell" else 1.01 limit_rate = stop_price * limit_price_pct
) else:
limit_rate = stop_price * limit_price_pct limit_rate = stop_price * (2 - limit_price_pct)
ordertype = "stop" ordertype = "stop"

View File

@ -55,8 +55,8 @@ class Kraken(Exchange):
orders = self._api.fetch_open_orders() orders = self._api.fetch_open_orders()
order_list = [(x["symbol"].split("/")[0 if x["side"] == "sell" else 1], order_list = [(x["symbol"].split("/")[0 if x["side"] == "sell" else 1],
x["remaining"] if x["side"] == "sell" else x["remaining"] * x["price"], x["remaining"] if x["side"] == "sell" else x["remaining"] * x["price"],
# Don't remove the below comment, this can be important for debugging # Don't remove the below comment, this can be important for debugging
# x["side"], x["amount"], # x["side"], x["amount"],
) for x in orders] ) for x in orders]
for bal in balances: for bal in balances:
@ -96,7 +96,10 @@ class Kraken(Exchange):
if order_types.get('stoploss', 'market') == 'limit': if order_types.get('stoploss', 'market') == 'limit':
ordertype = "stop-loss-limit" ordertype = "stop-loss-limit"
limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99) limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
limit_rate = stop_price * limit_price_pct if side == "sell":
limit_rate = stop_price * limit_price_pct
else:
limit_rate = stop_price * (2 - limit_price_pct)
params['price2'] = self.price_to_precision(pair, limit_rate) params['price2'] = self.price_to_precision(pair, limit_rate)
else: else:
ordertype = "stop-loss" ordertype = "stop-loss"
@ -144,13 +147,13 @@ class Kraken(Exchange):
for pair, market in self.markets.items(): for pair, market in self.markets.items():
info = market['info'] info = market['info']
leverage_buy = info['leverage_buy'] if 'leverage_buy' in info else [] leverage_buy = info.get('leverage_buy', [])
leverage_sell = info['leverage_sell'] if 'leverage_sell' in info else [] leverage_sell = info.get('leverage_sell', [])
if len(leverage_buy) > 0 or len(leverage_sell) > 0: if len(leverage_buy) > 0 or len(leverage_sell) > 0:
if leverage_buy != leverage_sell: if leverage_buy != leverage_sell:
logger.warning( logger.warning(
f"The buy({leverage_buy}) and sell({leverage_sell}) leverage are not equal" f"The buy({leverage_buy}) and sell({leverage_sell}) leverage are not equal"
"{pair}. Please let freqtrade know because this has never happened before" "for {pair}. Please notify freqtrade because this has never happened before"
) )
if max(leverage_buy) < max(leverage_sell): if max(leverage_buy) < max(leverage_sell):
leverages[pair] = leverage_buy leverages[pair] = leverage_buy

View File

@ -9,19 +9,18 @@ from tests.conftest import get_patched_exchange
from tests.exchange.test_exchange import ccxt_exceptionhandlers from tests.exchange.test_exchange import ccxt_exceptionhandlers
@pytest.mark.parametrize('limitratio,exchangelimitratio,expected,side', [ @pytest.mark.parametrize('limitratio,expected,side', [
(None, 1.05, 220 * 0.99, "sell"), (None, 220 * 0.99, "sell"),
(0.99, 1.05, 220 * 0.99, "sell"), (0.99, 220 * 0.99, "sell"),
(0.98, 1.05, 220 * 0.98, "sell"), (0.98, 220 * 0.98, "sell"),
(None, 0.95, 220 * 1.01, "buy"), (None, 220 * 1.01, "buy"),
(1.01, 0.95, 220 * 1.01, "buy"), (0.99, 220 * 1.01, "buy"),
(1.02, 0.95, 220 * 1.02, "buy"), (0.98, 220 * 1.02, "buy"),
]) ])
def test_stoploss_order_binance( def test_stoploss_order_binance(
default_conf, default_conf,
mocker, mocker,
limitratio, limitratio,
exchangelimitratio,
expected, expected,
side side
): ):
@ -47,7 +46,7 @@ def test_stoploss_order_binance(
amount=1, amount=1,
stop_price=190, stop_price=190,
side=side, side=side,
order_types={'stoploss_on_exchange_limit_ratio': exchangelimitratio} order_types={'stoploss_on_exchange_limit_ratio': 1.05}
) )
api_mock.create_order.reset_mock() api_mock.create_order.reset_mock()

View File

@ -168,11 +168,11 @@ def test_get_balances_prod(default_conf, mocker):
@pytest.mark.parametrize('ordertype', ['market', 'limit']) @pytest.mark.parametrize('ordertype', ['market', 'limit'])
@pytest.mark.parametrize('side,limitratio,adjustedprice', [ @pytest.mark.parametrize('side,adjustedprice', [
("buy", 0.99, 217.8), ("sell", 217.8),
("sell", 1.01, 222.2), ("buy", 222.2),
]) ])
def test_stoploss_order_kraken(default_conf, mocker, ordertype, side, limitratio, adjustedprice): def test_stoploss_order_kraken(default_conf, mocker, ordertype, side, adjustedprice):
api_mock = MagicMock() api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6)) order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
@ -189,10 +189,15 @@ def test_stoploss_order_kraken(default_conf, mocker, ordertype, side, limitratio
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken') exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, side=side, order = exchange.stoploss(
order_types={'stoploss': ordertype, pair='ETH/BTC',
'stoploss_on_exchange_limit_ratio': limitratio amount=1,
}) stop_price=220,
side=side,
order_types={
'stoploss': ordertype,
'stoploss_on_exchange_limit_ratio': 0.99
})
assert 'id' in order assert 'id' in order
assert 'info' in order assert 'info' in order
@ -201,7 +206,9 @@ def test_stoploss_order_kraken(default_conf, mocker, ordertype, side, limitratio
if ordertype == 'limit': if ordertype == 'limit':
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_LIMIT_ORDERTYPE assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_LIMIT_ORDERTYPE
assert api_mock.create_order.call_args_list[0][1]['params'] == { assert api_mock.create_order.call_args_list[0][1]['params'] == {
'trading_agreement': 'agree', 'price2': adjustedprice} 'trading_agreement': 'agree',
'price2': adjustedprice
}
else: else:
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
assert api_mock.create_order.call_args_list[0][1]['params'] == { assert api_mock.create_order.call_args_list[0][1]['params'] == {