Merge branch 'develop' into feat/short
This commit is contained in:
commit
7868e50141
@ -24,7 +24,7 @@ By default, loop runs every few seconds (`internals.process_throttle_secs`) and
|
|||||||
|
|
||||||
* Fetch open trades from persistence.
|
* Fetch open trades from persistence.
|
||||||
* Calculate current list of tradable pairs.
|
* Calculate current list of tradable pairs.
|
||||||
* Download ohlcv data for the pairlist including all [informative pairs](strategy-customization.md#get-data-for-non-tradeable-pairs)
|
* Download OHLCV data for the pairlist including all [informative pairs](strategy-customization.md#get-data-for-non-tradeable-pairs)
|
||||||
This step is only executed once per Candle to avoid unnecessary network traffic.
|
This step is only executed once per Candle to avoid unnecessary network traffic.
|
||||||
* Call `bot_loop_start()` strategy callback.
|
* Call `bot_loop_start()` strategy callback.
|
||||||
* Analyze strategy per pair.
|
* Analyze strategy per pair.
|
||||||
|
@ -210,6 +210,9 @@ OKX requires a passphrase for each api key, you will therefore need to add this
|
|||||||
|
|
||||||
## Gate.io
|
## Gate.io
|
||||||
|
|
||||||
|
!!! Tip "Stoploss on Exchange"
|
||||||
|
Gate.io supports `stoploss_on_exchange` and uses `stop-loss-limit` orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange..
|
||||||
|
|
||||||
Gate.io allows the use of `POINT` to pay for fees. As this is not a tradable currency (no regular market available), automatic fee calculations will fail (and default to a fee of 0).
|
Gate.io allows the use of `POINT` to pay for fees. As this is not a tradable currency (no regular market available), automatic fee calculations will fail (and default to a fee of 0).
|
||||||
The configuration parameter `exchange.unknown_fee_rate` can be used to specify the exchange rate between Point and the stake currency. Obviously, changing the stake-currency will also require changes to this value.
|
The configuration parameter `exchange.unknown_fee_rate` can be used to specify the exchange rate between Point and the stake currency. Obviously, changing the stake-currency will also require changes to this value.
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ These modes can be configured with these values:
|
|||||||
```
|
```
|
||||||
|
|
||||||
!!! Note
|
!!! Note
|
||||||
Stoploss on exchange is only supported for Binance (stop-loss-limit), Huobi (stop-limit), Kraken (stop-loss-market, stop-loss-limit), FTX (stop limit and stop-market) and kucoin (stop-limit and stop-market) as of now.
|
Stoploss on exchange is only supported for Binance (stop-loss-limit), Huobi (stop-limit), Kraken (stop-loss-market, stop-loss-limit), FTX (stop limit and stop-market) Gateio (stop-limit), and Kucoin (stop-limit and stop-market) as of now.
|
||||||
<ins>Do not set too low/tight stoploss value if using stop loss on exchange!</ins>
|
<ins>Do not set too low/tight stoploss value if using stop loss on exchange!</ins>
|
||||||
If set to low/tight then you have greater risk of missing fill on the order and stoploss will not work.
|
If set to low/tight then you have greater risk of missing fill on the order and stoploss will not work.
|
||||||
|
|
||||||
|
@ -517,20 +517,25 @@ Requires a configuration with specified `pairlists` attribute.
|
|||||||
Can be used to generate static pairlists to be used during backtesting / hyperopt.
|
Can be used to generate static pairlists to be used during backtesting / hyperopt.
|
||||||
|
|
||||||
```
|
```
|
||||||
usage: freqtrade test-pairlist [-h] [-c PATH]
|
usage: freqtrade test-pairlist [-h] [-v] [-c PATH]
|
||||||
[--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]]
|
[--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]]
|
||||||
[-1] [--print-json]
|
[-1] [--print-json] [--exchange EXCHANGE]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
|
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
|
||||||
-c PATH, --config PATH
|
-c PATH, --config PATH
|
||||||
Specify configuration file (default: `config.json`).
|
Specify configuration file (default:
|
||||||
Multiple --config options may be used. Can be set to
|
`userdir/config.json` or `config.json` whichever
|
||||||
`-` to read config from stdin.
|
exists). Multiple --config options may be used. Can be
|
||||||
|
set to `-` to read config from stdin.
|
||||||
--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]
|
--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]
|
||||||
Specify quote currency(-ies). Space-separated list.
|
Specify quote currency(-ies). Space-separated list.
|
||||||
-1, --one-column Print output in one column.
|
-1, --one-column Print output in one column.
|
||||||
--print-json Print list of pairs or market symbols in JSON format.
|
--print-json Print list of pairs or market symbols in JSON format.
|
||||||
|
--exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no
|
||||||
|
config is provided.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -52,7 +52,7 @@ ARGS_LIST_PAIRS = ["exchange", "print_list", "list_pairs_print_json", "print_one
|
|||||||
"trading_mode"]
|
"trading_mode"]
|
||||||
|
|
||||||
ARGS_TEST_PAIRLIST = ["verbosity", "config", "quote_currencies", "print_one_column",
|
ARGS_TEST_PAIRLIST = ["verbosity", "config", "quote_currencies", "print_one_column",
|
||||||
"list_pairs_print_json"]
|
"list_pairs_print_json", "exchange"]
|
||||||
|
|
||||||
ARGS_CREATE_USERDIR = ["user_data_dir", "reset"]
|
ARGS_CREATE_USERDIR = ["user_data_dir", "reset"]
|
||||||
|
|
||||||
|
@ -226,9 +226,11 @@ class Edge:
|
|||||||
"""
|
"""
|
||||||
final = []
|
final = []
|
||||||
for pair, info in self._cached_pairs.items():
|
for pair, info in self._cached_pairs.items():
|
||||||
if info.expectancy > float(self.edge_config.get('minimum_expectancy', 0.2)) and \
|
if (
|
||||||
info.winrate > float(self.edge_config.get('minimum_winrate', 0.60)) and \
|
info.expectancy > float(self.edge_config.get('minimum_expectancy', 0.2))
|
||||||
pair in pairs:
|
and info.winrate > float(self.edge_config.get('minimum_winrate', 0.60))
|
||||||
|
and pair in pairs
|
||||||
|
):
|
||||||
final.append(pair)
|
final.append(pair)
|
||||||
|
|
||||||
if self._final_pairs != final:
|
if self._final_pairs != final:
|
||||||
@ -253,8 +255,8 @@ class Edge:
|
|||||||
"""
|
"""
|
||||||
final = []
|
final = []
|
||||||
for pair, info in self._cached_pairs.items():
|
for pair, info in self._cached_pairs.items():
|
||||||
if info.expectancy > float(self.edge_config.get('minimum_expectancy', 0.2)) and \
|
if (info.expectancy > float(self.edge_config.get('minimum_expectancy', 0.2)) and
|
||||||
info.winrate > float(self.edge_config.get('minimum_winrate', 0.60)):
|
info.winrate > float(self.edge_config.get('minimum_winrate', 0.60))):
|
||||||
final.append({
|
final.append({
|
||||||
'Pair': pair,
|
'Pair': pair,
|
||||||
'Winrate': info.winrate,
|
'Winrate': info.winrate,
|
||||||
|
@ -1124,11 +1124,11 @@ class Exchange:
|
|||||||
raise OperationalException(e) from e
|
raise OperationalException(e) from e
|
||||||
|
|
||||||
@retrier(retries=API_FETCH_ORDER_RETRY_COUNT)
|
@retrier(retries=API_FETCH_ORDER_RETRY_COUNT)
|
||||||
def fetch_order(self, order_id: str, pair: str) -> Dict:
|
def fetch_order(self, order_id: str, pair: str, params={}) -> Dict:
|
||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
return self.fetch_dry_run_order(order_id)
|
return self.fetch_dry_run_order(order_id)
|
||||||
try:
|
try:
|
||||||
order = self._api.fetch_order(order_id, pair)
|
order = self._api.fetch_order(order_id, pair, params=params)
|
||||||
self._log_exchange_response('fetch_order', order)
|
self._log_exchange_response('fetch_order', order)
|
||||||
order = self._order_contracts_to_amount(order)
|
order = self._order_contracts_to_amount(order)
|
||||||
return order
|
return order
|
||||||
@ -1172,7 +1172,7 @@ class Exchange:
|
|||||||
and order.get('filled') == 0.0)
|
and order.get('filled') == 0.0)
|
||||||
|
|
||||||
@retrier
|
@retrier
|
||||||
def cancel_order(self, order_id: str, pair: str) -> Dict:
|
def cancel_order(self, order_id: str, pair: str, params={}) -> Dict:
|
||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
try:
|
try:
|
||||||
order = self.fetch_dry_run_order(order_id)
|
order = self.fetch_dry_run_order(order_id)
|
||||||
@ -1183,7 +1183,7 @@ class Exchange:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
order = self._api.cancel_order(order_id, pair)
|
order = self._api.cancel_order(order_id, pair, params=params)
|
||||||
self._log_exchange_response('cancel_order', order)
|
self._log_exchange_response('cancel_order', order)
|
||||||
order = self._order_contracts_to_amount(order)
|
order = self._order_contracts_to_amount(order)
|
||||||
return order
|
return order
|
||||||
|
@ -23,10 +23,10 @@ class Gateio(Exchange):
|
|||||||
_ft_has: Dict = {
|
_ft_has: Dict = {
|
||||||
"ohlcv_candle_limit": 1000,
|
"ohlcv_candle_limit": 1000,
|
||||||
"ohlcv_volume_currency": "quote",
|
"ohlcv_volume_currency": "quote",
|
||||||
|
"stoploss_order_types": {"limit": "limit"},
|
||||||
|
"stoploss_on_exchange": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
_headers = {'X-Gate-Channel-Id': 'freqtrade'}
|
|
||||||
|
|
||||||
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
|
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
# (TradingMode.MARGIN, MarginMode.CROSS),
|
# (TradingMode.MARGIN, MarginMode.CROSS),
|
||||||
@ -41,3 +41,24 @@ class Gateio(Exchange):
|
|||||||
if any(v == 'market' for k, v in order_types.items()):
|
if any(v == 'market' for k, v in order_types.items()):
|
||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
f'Exchange {self.name} does not support market orders.')
|
f'Exchange {self.name} does not support market orders.')
|
||||||
|
|
||||||
|
def fetch_stoploss_order(self, order_id: str, pair: str, params={}) -> Dict:
|
||||||
|
return self.fetch_order(
|
||||||
|
order_id=order_id,
|
||||||
|
pair=pair,
|
||||||
|
params={'stop': True}
|
||||||
|
)
|
||||||
|
|
||||||
|
def cancel_stoploss_order(self, order_id: str, pair: str, params={}) -> Dict:
|
||||||
|
return self.cancel_order(
|
||||||
|
order_id=order_id,
|
||||||
|
pair=pair,
|
||||||
|
params={'stop': True}
|
||||||
|
)
|
||||||
|
|
||||||
|
def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool:
|
||||||
|
"""
|
||||||
|
Verify stop_loss against stoploss-order value (limit or price)
|
||||||
|
Returns True if adjustment is necessary.
|
||||||
|
"""
|
||||||
|
return stop_loss > float(order['stopPrice'])
|
||||||
|
@ -4,6 +4,7 @@ Spread pair list filter
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.plugins.pairlist.IPairList import IPairList
|
from freqtrade.plugins.pairlist.IPairList import IPairList
|
||||||
|
|
||||||
|
|
||||||
@ -20,6 +21,12 @@ class SpreadFilter(IPairList):
|
|||||||
self._max_spread_ratio = pairlistconfig.get('max_spread_ratio', 0.005)
|
self._max_spread_ratio = pairlistconfig.get('max_spread_ratio', 0.005)
|
||||||
self._enabled = self._max_spread_ratio != 0
|
self._enabled = self._max_spread_ratio != 0
|
||||||
|
|
||||||
|
if not self._exchange.exchange_has('fetchTickers'):
|
||||||
|
raise OperationalException(
|
||||||
|
'Exchange does not support fetchTickers, therefore SpreadFilter cannot be used.'
|
||||||
|
'Please edit your config and restart the bot.'
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def needstickers(self) -> bool:
|
def needstickers(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -592,7 +592,7 @@ class RPC:
|
|||||||
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)
|
||||||
rate = tickers.get(pair, {}).get('bid', None)
|
rate = tickers.get(pair, {}).get('last', None)
|
||||||
if rate:
|
if rate:
|
||||||
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
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
coveralls==3.3.1
|
coveralls==3.3.1
|
||||||
flake8==4.0.1
|
flake8==4.0.1
|
||||||
flake8-tidy-imports==4.6.0
|
flake8-tidy-imports==4.6.0
|
||||||
mypy==0.931
|
mypy==0.940
|
||||||
pytest==7.0.1
|
pytest==7.1.0
|
||||||
pytest-asyncio==0.18.2
|
pytest-asyncio==0.18.2
|
||||||
pytest-cov==3.0.0
|
pytest-cov==3.0.0
|
||||||
pytest-mock==3.7.0
|
pytest-mock==3.7.0
|
||||||
@ -17,12 +17,12 @@ isort==5.10.1
|
|||||||
time-machine==2.6.0
|
time-machine==2.6.0
|
||||||
|
|
||||||
# Convert jupyter notebooks to markdown documents
|
# Convert jupyter notebooks to markdown documents
|
||||||
nbconvert==6.4.2
|
nbconvert==6.4.4
|
||||||
|
|
||||||
# mypy types
|
# mypy types
|
||||||
types-cachetools==4.2.10
|
types-cachetools==5.0.0
|
||||||
types-filelock==3.2.5
|
types-filelock==3.2.5
|
||||||
types-requests==2.27.11
|
types-requests==2.27.12
|
||||||
types-tabulate==0.8.5
|
types-tabulate==0.8.5
|
||||||
|
|
||||||
# Extensions to datetime library
|
# Extensions to datetime library
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
numpy==1.22.2
|
numpy==1.22.3
|
||||||
pandas==1.4.1
|
pandas==1.4.1
|
||||||
pandas-ta==0.3.14b
|
pandas-ta==0.3.14b
|
||||||
|
|
||||||
ccxt==1.75.12
|
ccxt==1.76.5
|
||||||
# Pin cryptography for now due to rust build errors with piwheels
|
# Pin cryptography for now due to rust build errors with piwheels
|
||||||
cryptography==36.0.1
|
cryptography==36.0.1
|
||||||
aiohttp==3.8.1
|
aiohttp==3.8.1
|
||||||
@ -32,7 +32,7 @@ sdnotify==0.3.2
|
|||||||
|
|
||||||
# API Server
|
# API Server
|
||||||
fastapi==0.75.0
|
fastapi==0.75.0
|
||||||
uvicorn==0.17.5
|
uvicorn==0.17.6
|
||||||
pyjwt==2.3.0
|
pyjwt==2.3.0
|
||||||
aiofiles==0.8.0
|
aiofiles==0.8.0
|
||||||
psutil==5.9.0
|
psutil==5.9.0
|
||||||
|
2
setup.py
2
setup.py
@ -42,7 +42,7 @@ setup(
|
|||||||
],
|
],
|
||||||
install_requires=[
|
install_requires=[
|
||||||
# from requirements.txt
|
# from requirements.txt
|
||||||
'ccxt>=1.74.17',
|
'ccxt>=1.76.5',
|
||||||
'SQLAlchemy',
|
'SQLAlchemy',
|
||||||
'python-telegram-bot>=13.4',
|
'python-telegram-bot>=13.4',
|
||||||
'arrow>=0.17.0',
|
'arrow>=0.17.0',
|
||||||
|
@ -2720,37 +2720,36 @@ def test_cancel_stoploss_order_with_result(default_conf, mocker, exchange_name):
|
|||||||
default_conf['dry_run'] = False
|
default_conf['dry_run'] = False
|
||||||
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', return_value={'for': 123})
|
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', return_value={'for': 123})
|
||||||
mocker.patch('freqtrade.exchange.Ftx.fetch_stoploss_order', return_value={'for': 123})
|
mocker.patch('freqtrade.exchange.Ftx.fetch_stoploss_order', return_value={'for': 123})
|
||||||
|
mocker.patch('freqtrade.exchange.Gateio.fetch_stoploss_order', return_value={'for': 123})
|
||||||
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
||||||
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order',
|
res = {'fee': {}, 'status': 'canceled', 'amount': 1234}
|
||||||
return_value={'fee': {}, 'status': 'canceled', 'amount': 1234})
|
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', return_value=res)
|
||||||
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order',
|
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order', return_value=res)
|
||||||
return_value={'fee': {}, 'status': 'canceled', 'amount': 1234})
|
mocker.patch('freqtrade.exchange.Gateio.cancel_stoploss_order', return_value=res)
|
||||||
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
||||||
assert co == {'fee': {}, 'status': 'canceled', 'amount': 1234}
|
assert co == res
|
||||||
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order',
|
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', return_value='canceled')
|
||||||
return_value='canceled')
|
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order', return_value='canceled')
|
||||||
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order',
|
mocker.patch('freqtrade.exchange.Gateio.cancel_stoploss_order', return_value='canceled')
|
||||||
return_value='canceled')
|
|
||||||
# Fall back to fetch_stoploss_order
|
# Fall back to fetch_stoploss_order
|
||||||
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
||||||
assert co == {'for': 123}
|
assert co == {'for': 123}
|
||||||
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order',
|
exc = InvalidOrderException("")
|
||||||
side_effect=InvalidOrderException(""))
|
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', side_effect=exc)
|
||||||
mocker.patch('freqtrade.exchange.Ftx.fetch_stoploss_order',
|
mocker.patch('freqtrade.exchange.Ftx.fetch_stoploss_order', side_effect=exc)
|
||||||
side_effect=InvalidOrderException(""))
|
mocker.patch('freqtrade.exchange.Gateio.fetch_stoploss_order', side_effect=exc)
|
||||||
|
|
||||||
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
||||||
assert co['amount'] == 555
|
assert co['amount'] == 555
|
||||||
assert co == {'fee': {}, 'status': 'canceled', 'amount': 555, 'info': {}}
|
assert co == {'fee': {}, 'status': 'canceled', 'amount': 555, 'info': {}}
|
||||||
|
|
||||||
with pytest.raises(InvalidOrderException):
|
with pytest.raises(InvalidOrderException):
|
||||||
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order',
|
exc = InvalidOrderException("Did not find order")
|
||||||
side_effect=InvalidOrderException("Did not find order"))
|
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', side_effect=exc)
|
||||||
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order',
|
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order', side_effect=exc)
|
||||||
side_effect=InvalidOrderException("Did not find order"))
|
mocker.patch('freqtrade.exchange.Gateio.cancel_stoploss_order', side_effect=exc)
|
||||||
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
||||||
exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=123)
|
exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=123)
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.exchange import Gateio
|
from freqtrade.exchange import Gateio
|
||||||
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
|
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
|
||||||
|
from tests.conftest import get_patched_exchange
|
||||||
|
|
||||||
|
|
||||||
def test_validate_order_types_gateio(default_conf, mocker):
|
def test_validate_order_types_gateio(default_conf, mocker):
|
||||||
@ -26,3 +29,39 @@ def test_validate_order_types_gateio(default_conf, mocker):
|
|||||||
with pytest.raises(OperationalException,
|
with pytest.raises(OperationalException,
|
||||||
match=r'Exchange .* does not support market orders.'):
|
match=r'Exchange .* does not support market orders.'):
|
||||||
ExchangeResolver.load_exchange('gateio', default_conf, True)
|
ExchangeResolver.load_exchange('gateio', default_conf, True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_stoploss_order_gateio(default_conf, mocker):
|
||||||
|
exchange = get_patched_exchange(mocker, default_conf, id='gateio')
|
||||||
|
|
||||||
|
fetch_order_mock = MagicMock()
|
||||||
|
exchange.fetch_order = fetch_order_mock
|
||||||
|
|
||||||
|
exchange.fetch_stoploss_order('1234', 'ETH/BTC')
|
||||||
|
assert fetch_order_mock.call_count == 1
|
||||||
|
assert fetch_order_mock.call_args_list[0][1]['order_id'] == '1234'
|
||||||
|
assert fetch_order_mock.call_args_list[0][1]['pair'] == 'ETH/BTC'
|
||||||
|
assert fetch_order_mock.call_args_list[0][1]['params'] == {'stop': True}
|
||||||
|
|
||||||
|
|
||||||
|
def test_cancel_stoploss_order_gateio(default_conf, mocker):
|
||||||
|
exchange = get_patched_exchange(mocker, default_conf, id='gateio')
|
||||||
|
|
||||||
|
cancel_order_mock = MagicMock()
|
||||||
|
exchange.cancel_order = cancel_order_mock
|
||||||
|
|
||||||
|
exchange.cancel_stoploss_order('1234', 'ETH/BTC')
|
||||||
|
assert cancel_order_mock.call_count == 1
|
||||||
|
assert cancel_order_mock.call_args_list[0][1]['order_id'] == '1234'
|
||||||
|
assert cancel_order_mock.call_args_list[0][1]['pair'] == 'ETH/BTC'
|
||||||
|
assert cancel_order_mock.call_args_list[0][1]['params'] == {'stop': True}
|
||||||
|
|
||||||
|
|
||||||
|
def test_stoploss_adjust_gateio(mocker, default_conf):
|
||||||
|
exchange = get_patched_exchange(mocker, default_conf, id='gateio')
|
||||||
|
order = {
|
||||||
|
'price': 1500,
|
||||||
|
'stopPrice': 1500,
|
||||||
|
}
|
||||||
|
assert exchange.stoploss_adjust(1501, order)
|
||||||
|
assert not exchange.stoploss_adjust(1499, order)
|
||||||
|
@ -782,6 +782,19 @@ def test_gen_pair_whitelist_not_supported(mocker, default_conf, tickers) -> None
|
|||||||
get_patched_freqtradebot(mocker, default_conf)
|
get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pair_whitelist_not_supported_Spread(mocker, default_conf, tickers) -> None:
|
||||||
|
default_conf['pairlists'] = [{'method': 'StaticPairList'}, {'method': 'SpreadFilter'}]
|
||||||
|
|
||||||
|
mocker.patch.multiple('freqtrade.exchange.Exchange',
|
||||||
|
get_tickers=tickers,
|
||||||
|
exchange_has=MagicMock(return_value=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(OperationalException,
|
||||||
|
match=r'Exchange does not support fetchTickers, .*'):
|
||||||
|
get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("pairlist", AVAILABLE_PAIRLISTS)
|
@pytest.mark.parametrize("pairlist", AVAILABLE_PAIRLISTS)
|
||||||
def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):
|
def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):
|
||||||
whitelist_conf['pairlists'][0]['method'] = pairlist
|
whitelist_conf['pairlists'][0]['method'] = pairlist
|
||||||
|
@ -650,8 +650,8 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
|
|||||||
rpc._fiat_converter = CryptoToFiatConverter()
|
rpc._fiat_converter = CryptoToFiatConverter()
|
||||||
|
|
||||||
result = rpc._rpc_balance(default_conf['stake_currency'], default_conf['fiat_display_currency'])
|
result = rpc._rpc_balance(default_conf['stake_currency'], default_conf['fiat_display_currency'])
|
||||||
assert prec_satoshi(result['total'], 30.309096315)
|
assert prec_satoshi(result['total'], 30.30909624)
|
||||||
assert prec_satoshi(result['value'], 454636.44472997)
|
assert prec_satoshi(result['value'], 454636.44360691)
|
||||||
assert tickers.call_count == 1
|
assert tickers.call_count == 1
|
||||||
assert tickers.call_args_list[0][1]['cached'] is True
|
assert tickers.call_args_list[0][1]['cached'] is True
|
||||||
assert 'USD' == result['symbol']
|
assert 'USD' == result['symbol']
|
||||||
@ -685,7 +685,7 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
|
|||||||
'free': 5.0,
|
'free': 5.0,
|
||||||
'balance': 10.0,
|
'balance': 10.0,
|
||||||
'currency': 'USDT',
|
'currency': 'USDT',
|
||||||
'est_stake': 0.0011563153318162476,
|
'est_stake': 0.0011562404610161968,
|
||||||
'used': 5.0,
|
'used': 5.0,
|
||||||
'stake': 'BTC',
|
'stake': 'BTC',
|
||||||
'is_position': False,
|
'is_position': False,
|
||||||
|
@ -26,7 +26,9 @@ def test_ttl_cache():
|
|||||||
assert 'a' in cache1h
|
assert 'a' in cache1h
|
||||||
|
|
||||||
t.move_to("2021-09-01 05:59:59 +00:00")
|
t.move_to("2021-09-01 05:59:59 +00:00")
|
||||||
|
assert 'a' not in cache
|
||||||
assert 'a' in cache1h
|
assert 'a' in cache1h
|
||||||
|
|
||||||
t.move_to("2021-09-01 06:00:00 +00:00")
|
t.move_to("2021-09-01 06:00:00 +00:00")
|
||||||
|
assert 'a' not in cache
|
||||||
assert 'a' not in cache1h
|
assert 'a' not in cache1h
|
||||||
|
Loading…
Reference in New Issue
Block a user