Merge branch 'develop' into main_refactoring
This commit is contained in:
@@ -4,7 +4,6 @@ import logging
|
||||
import re
|
||||
from datetime import datetime
|
||||
from functools import reduce
|
||||
from typing import Dict, Optional
|
||||
from unittest.mock import MagicMock, PropertyMock
|
||||
|
||||
import arrow
|
||||
@@ -13,11 +12,11 @@ from telegram import Chat, Message, Update
|
||||
|
||||
from freqtrade import constants
|
||||
from freqtrade.data.converter import parse_ticker_dataframe
|
||||
from freqtrade.exchange import Exchange
|
||||
from freqtrade.edge import Edge, PairInfo
|
||||
from freqtrade.worker import Worker
|
||||
from freqtrade.exchange import Exchange
|
||||
from freqtrade.freqtradebot import FreqtradeBot
|
||||
from freqtrade.resolvers import ExchangeResolver
|
||||
from freqtrade.worker import Worker
|
||||
|
||||
logging.getLogger('').setLevel(logging.INFO)
|
||||
|
||||
@@ -96,7 +95,6 @@ def patch_freqtradebot(mocker, config) -> None:
|
||||
:param config: Config to pass to the bot
|
||||
:return: None
|
||||
"""
|
||||
patch_coinmarketcap(mocker, {'price_usd': 12345.0})
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
|
||||
patch_exchange(mocker, None)
|
||||
@@ -114,7 +112,8 @@ def get_patched_worker(mocker, config) -> Worker:
|
||||
return Worker(args=None, config=config)
|
||||
|
||||
|
||||
def patch_coinmarketcap(mocker, value: Optional[Dict[str, float]] = None) -> None:
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_coinmarketcap(mocker) -> None:
|
||||
"""
|
||||
Mocker to coinmarketcap to speed up tests
|
||||
:param mocker: mocker to patch coinmarketcap class
|
||||
|
@@ -28,6 +28,7 @@ class BTContainer(NamedTuple):
|
||||
roi: float
|
||||
trades: List[BTrade]
|
||||
profit_perc: float
|
||||
trailing_stop: bool = False
|
||||
|
||||
|
||||
def _get_frame_time_from_offset(offset):
|
||||
|
@@ -14,10 +14,10 @@ from freqtrade.tests.optimize import (BTrade, BTContainer, _build_backtest_dataf
|
||||
from freqtrade.tests.conftest import patch_exchange
|
||||
|
||||
|
||||
# Test 0 Minus 8% Close
|
||||
# Test 1 Minus 8% Close
|
||||
# Test with Stop-loss at 1%
|
||||
# TC1: Stop-Loss Triggered 1% loss
|
||||
tc0 = BTContainer(data=[
|
||||
tc1 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
|
||||
[1, 5000, 5025, 4975, 4987, 6172, 0, 0], # enter trade (signal on last candle)
|
||||
@@ -30,10 +30,10 @@ tc0 = BTContainer(data=[
|
||||
)
|
||||
|
||||
|
||||
# Test 1 Minus 4% Low, minus 1% close
|
||||
# Test 2 Minus 4% Low, minus 1% close
|
||||
# Test with Stop-Loss at 3%
|
||||
# TC2: Stop-Loss Triggered 3% Loss
|
||||
tc1 = BTContainer(data=[
|
||||
tc2 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
|
||||
[1, 5000, 5025, 4975, 4987, 6172, 0, 0], # enter trade (signal on last candle)
|
||||
@@ -49,11 +49,10 @@ tc1 = BTContainer(data=[
|
||||
# Test 3 Candle drops 4%, Recovers 1%.
|
||||
# Entry Criteria Met
|
||||
# Candle drops 20%
|
||||
# Candle Data for test 3
|
||||
# Test with Stop-Loss at 2%
|
||||
# TC3: Trade-A: Stop-Loss Triggered 2% Loss
|
||||
# Trade-B: Stop-Loss Triggered 2% Loss
|
||||
tc2 = BTContainer(data=[
|
||||
tc3 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
|
||||
[1, 5000, 5025, 4975, 4987, 6172, 0, 0], # enter trade (signal on last candle)
|
||||
@@ -71,7 +70,7 @@ tc2 = BTContainer(data=[
|
||||
# Candle Data for test 3 – Candle drops 3% Closed 15% up
|
||||
# Test with Stop-loss at 2% ROI 6%
|
||||
# TC4: Stop-Loss Triggered 2% Loss
|
||||
tc3 = BTContainer(data=[
|
||||
tc4 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
|
||||
[1, 5000, 5025, 4975, 4987, 6172, 0, 0], # enter trade (signal on last candle)
|
||||
@@ -83,10 +82,10 @@ tc3 = BTContainer(data=[
|
||||
trades=[BTrade(sell_reason=SellType.STOP_LOSS, open_tick=1, close_tick=2)]
|
||||
)
|
||||
|
||||
# Test 4 / Drops 0.5% Closes +20%
|
||||
# Test 5 / Drops 0.5% Closes +20%
|
||||
# Set stop-loss at 1% ROI 3%
|
||||
# TC5: ROI triggers 3% Gain
|
||||
tc4 = BTContainer(data=[
|
||||
tc5 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5025, 4980, 4987, 6172, 1, 0],
|
||||
[1, 5000, 5025, 4980, 4987, 6172, 0, 0], # enter trade (signal on last candle)
|
||||
@@ -99,10 +98,9 @@ tc4 = BTContainer(data=[
|
||||
)
|
||||
|
||||
# Test 6 / Drops 3% / Recovers 6% Positive / Closes 1% positve
|
||||
# Candle Data for test 6
|
||||
# Set stop-loss at 2% ROI at 5%
|
||||
# TC6: Stop-Loss triggers 2% Loss
|
||||
tc5 = BTContainer(data=[
|
||||
tc6 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
|
||||
[1, 5000, 5025, 4975, 4987, 6172, 0, 0], # enter trade (signal on last candle)
|
||||
@@ -115,10 +113,9 @@ tc5 = BTContainer(data=[
|
||||
)
|
||||
|
||||
# Test 7 - 6% Positive / 1% Negative / Close 1% Positve
|
||||
# Candle Data for test 7
|
||||
# Set stop-loss at 2% ROI at 3%
|
||||
# TC7: ROI Triggers 3% Gain
|
||||
tc6 = BTContainer(data=[
|
||||
tc7 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
|
||||
[1, 5000, 5025, 4975, 4987, 6172, 0, 0],
|
||||
@@ -130,14 +127,47 @@ tc6 = BTContainer(data=[
|
||||
trades=[BTrade(sell_reason=SellType.ROI, open_tick=1, close_tick=2)]
|
||||
)
|
||||
|
||||
|
||||
# Test 8 - trailing_stop should raise so candle 3 causes a stoploss.
|
||||
# Set stop-loss at 10%, ROI at 10% (should not apply)
|
||||
# TC8: Trailing stoploss - stoploss should be adjusted candle 2
|
||||
tc8 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
|
||||
[1, 5000, 5050, 4950, 5000, 6172, 0, 0],
|
||||
[2, 5000, 5250, 4750, 4850, 6172, 0, 0],
|
||||
[3, 4850, 5050, 4650, 4750, 6172, 0, 0],
|
||||
[4, 4750, 4950, 4350, 4750, 6172, 0, 0]],
|
||||
stop_loss=-0.10, roi=0.10, profit_perc=-0.055, trailing_stop=True,
|
||||
trades=[BTrade(sell_reason=SellType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)]
|
||||
)
|
||||
|
||||
|
||||
# Test 9 - trailing_stop should raise - high and low in same candle.
|
||||
# Candle Data for test 9
|
||||
# Set stop-loss at 10%, ROI at 10% (should not apply)
|
||||
# TC9: Trailing stoploss - stoploss should be adjusted candle 2
|
||||
tc9 = BTContainer(data=[
|
||||
# D O H L C V B S
|
||||
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
|
||||
[1, 5000, 5050, 4950, 5000, 6172, 0, 0],
|
||||
[2, 5000, 5050, 4950, 5000, 6172, 0, 0],
|
||||
[3, 5000, 5200, 4550, 4850, 6172, 0, 0],
|
||||
[4, 4750, 4950, 4350, 4750, 6172, 0, 0]],
|
||||
stop_loss=-0.10, roi=0.10, profit_perc=-0.064, trailing_stop=True,
|
||||
trades=[BTrade(sell_reason=SellType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)]
|
||||
)
|
||||
|
||||
TESTS = [
|
||||
tc0,
|
||||
tc1,
|
||||
tc2,
|
||||
tc3,
|
||||
tc4,
|
||||
tc5,
|
||||
tc6,
|
||||
tc7,
|
||||
tc8,
|
||||
tc9,
|
||||
]
|
||||
|
||||
|
||||
@@ -148,8 +178,9 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None:
|
||||
"""
|
||||
default_conf["stoploss"] = data.stop_loss
|
||||
default_conf["minimal_roi"] = {"0": data.roi}
|
||||
default_conf['ticker_interval'] = tests_ticker_interval
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.0))
|
||||
default_conf["ticker_interval"] = tests_ticker_interval
|
||||
default_conf["trailing_stop"] = data.trailing_stop
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_fee", MagicMock(return_value=0.0))
|
||||
patch_exchange(mocker)
|
||||
frame = _build_backtest_dataframe(data.data)
|
||||
backtesting = Backtesting(default_conf)
|
||||
@@ -157,7 +188,7 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None:
|
||||
backtesting.advise_sell = lambda a, m: frame
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
pair = 'UNITTEST/BTC'
|
||||
pair = "UNITTEST/BTC"
|
||||
# Dummy data as we mock the analyze functions
|
||||
data_processed = {pair: DataFrame()}
|
||||
min_date, max_date = get_timeframe({pair: frame})
|
||||
|
@@ -8,7 +8,7 @@ import pytest
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
from freqtrade.rpc.fiat_convert import CryptoFiat, CryptoToFiatConverter
|
||||
from freqtrade.tests.conftest import log_has, patch_coinmarketcap
|
||||
from freqtrade.tests.conftest import log_has
|
||||
|
||||
|
||||
def test_pair_convertion_object():
|
||||
@@ -40,7 +40,6 @@ def test_pair_convertion_object():
|
||||
|
||||
|
||||
def test_fiat_convert_is_supported(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert fiat_convert._is_supported_fiat(fiat='USD') is True
|
||||
assert fiat_convert._is_supported_fiat(fiat='usd') is True
|
||||
@@ -49,7 +48,6 @@ def test_fiat_convert_is_supported(mocker):
|
||||
|
||||
|
||||
def test_fiat_convert_add_pair(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
@@ -72,8 +70,6 @@ def test_fiat_convert_add_pair(mocker):
|
||||
|
||||
|
||||
def test_fiat_convert_find_price(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
with pytest.raises(ValueError, match=r'The fiat ABC is not supported.'):
|
||||
@@ -93,15 +89,12 @@ def test_fiat_convert_find_price(mocker):
|
||||
|
||||
def test_fiat_convert_unsupported_crypto(mocker, caplog):
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._cryptomap', return_value=[])
|
||||
patch_coinmarketcap(mocker)
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert fiat_convert._find_price(crypto_symbol='CRYPTO_123', fiat_symbol='EUR') == 0.0
|
||||
assert log_has('unsupported crypto-symbol CRYPTO_123 - returning 0.0', caplog.record_tuples)
|
||||
|
||||
|
||||
def test_fiat_convert_get_price(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
||||
return_value=28000.0)
|
||||
|
||||
@@ -134,21 +127,18 @@ def test_fiat_convert_get_price(mocker):
|
||||
|
||||
|
||||
def test_fiat_convert_same_currencies(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
assert fiat_convert.get_price(crypto_symbol='USD', fiat_symbol='USD') == 1.0
|
||||
|
||||
|
||||
def test_fiat_convert_two_FIAT(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
assert fiat_convert.get_price(crypto_symbol='USD', fiat_symbol='EUR') == 0.0
|
||||
|
||||
|
||||
def test_loadcryptomap(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert len(fiat_convert._cryptomap) == 2
|
||||
@@ -174,7 +164,6 @@ def test_fiat_init_network_exception(mocker):
|
||||
|
||||
def test_fiat_convert_without_network(mocker):
|
||||
# Because CryptoToFiatConverter is a Singleton we reset the value of _coinmarketcap
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
@@ -205,7 +194,6 @@ def test_fiat_invalid_response(mocker, caplog):
|
||||
|
||||
|
||||
def test_convert_amount(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter.get_price', return_value=12345.0)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
@@ -14,7 +14,7 @@ from freqtrade.persistence import Trade
|
||||
from freqtrade.rpc import RPC, RPCException
|
||||
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
|
||||
from freqtrade.state import State
|
||||
from freqtrade.tests.conftest import patch_coinmarketcap, patch_exchange
|
||||
from freqtrade.tests.conftest import patch_exchange
|
||||
from freqtrade.tests.test_freqtradebot import patch_get_signal
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ def prec_satoshi(a, b) -> float:
|
||||
|
||||
# Unit tests
|
||||
def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -60,6 +59,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
|
||||
'amount': 90.99181074,
|
||||
'close_profit': None,
|
||||
'current_profit': -0.59,
|
||||
'stop_loss': 0.0,
|
||||
'initial_stop_loss': 0.0,
|
||||
'initial_stop_loss_pct': None,
|
||||
'stop_loss_pct': None,
|
||||
'open_order': '(limit buy rem=0.00000000)'
|
||||
} == results[0]
|
||||
|
||||
@@ -80,12 +83,15 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
|
||||
'amount': 90.99181074,
|
||||
'close_profit': None,
|
||||
'current_profit': ANY,
|
||||
'stop_loss': 0.0,
|
||||
'initial_stop_loss': 0.0,
|
||||
'initial_stop_loss_pct': None,
|
||||
'stop_loss_pct': None,
|
||||
'open_order': '(limit buy rem=0.00000000)'
|
||||
} == results[0]
|
||||
|
||||
|
||||
def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -122,7 +128,6 @@ def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
|
||||
|
||||
def test_rpc_daily_profit(default_conf, update, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -176,7 +181,6 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
|
||||
'freqtrade.rpc.fiat_convert.Market',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
)
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
@@ -336,7 +340,6 @@ def test_rpc_balance_handle(default_conf, mocker):
|
||||
'freqtrade.rpc.fiat_convert.Market',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
)
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
@@ -367,7 +370,6 @@ def test_rpc_balance_handle(default_conf, mocker):
|
||||
|
||||
|
||||
def test_rpc_start(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -391,7 +393,6 @@ def test_rpc_start(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_stop(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -416,7 +417,6 @@ def test_rpc_stop(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_stopbuy(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -437,7 +437,6 @@ def test_rpc_stopbuy(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
|
||||
@@ -539,7 +538,6 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
|
||||
|
||||
def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -576,7 +574,6 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
|
||||
|
||||
def test_rpc_count(mocker, default_conf, ticker, fee, markets) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -605,7 +602,6 @@ def test_rpc_count(mocker, default_conf, ticker, fee, markets) -> None:
|
||||
|
||||
def test_rpcforcebuy(mocker, default_conf, ticker, fee, markets, limit_buy_order) -> None:
|
||||
default_conf['forcebuy_enable'] = True
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
buy_mm = MagicMock(return_value={'id': limit_buy_order['id']})
|
||||
@@ -657,7 +653,6 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, markets, limit_buy_order
|
||||
def test_rpcforcebuy_stopped(mocker, default_conf) -> None:
|
||||
default_conf['forcebuy_enable'] = True
|
||||
default_conf['initial_state'] = 'stopped'
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
|
||||
@@ -671,7 +666,6 @@ def test_rpcforcebuy_stopped(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpcforcebuy_disabled(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
|
||||
@@ -685,7 +679,6 @@ def test_rpcforcebuy_disabled(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_whitelist(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
|
||||
@@ -698,7 +691,6 @@ def test_rpc_whitelist(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_whitelist_dynamic(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
default_conf['pairlist'] = {'method': 'VolumePairList',
|
||||
'config': {'number_assets': 4}
|
||||
@@ -716,7 +708,6 @@ def test_rpc_whitelist_dynamic(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_blacklist(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
|
||||
@@ -736,7 +727,6 @@ def test_rpc_blacklist(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_edge_disabled(mocker, default_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
freqtradebot = FreqtradeBot(default_conf)
|
||||
@@ -746,7 +736,6 @@ def test_rpc_edge_disabled(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_rpc_edge_enabled(mocker, edge_conf) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch('freqtrade.edge.Edge._cached_pairs', mocker.PropertyMock(
|
||||
|
@@ -20,8 +20,7 @@ from freqtrade.rpc import RPCMessageType
|
||||
from freqtrade.rpc.telegram import Telegram, authorized_only
|
||||
from freqtrade.state import State
|
||||
from freqtrade.strategy.interface import SellType
|
||||
from freqtrade.tests.conftest import (get_patched_freqtradebot,
|
||||
log_has, patch_coinmarketcap, patch_exchange)
|
||||
from freqtrade.tests.conftest import (get_patched_freqtradebot, log_has, patch_exchange)
|
||||
from freqtrade.tests.test_freqtradebot import patch_get_signal
|
||||
|
||||
|
||||
@@ -90,7 +89,6 @@ def test_cleanup(default_conf, mocker) -> None:
|
||||
|
||||
|
||||
def test_authorized_only(default_conf, mocker, caplog) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker, None)
|
||||
|
||||
chat = Chat(0, 0)
|
||||
@@ -120,7 +118,6 @@ def test_authorized_only(default_conf, mocker, caplog) -> None:
|
||||
|
||||
|
||||
def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker, None)
|
||||
chat = Chat(0xdeadbeef, 0)
|
||||
update = Update(randint(1, 100))
|
||||
@@ -149,7 +146,6 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
|
||||
|
||||
|
||||
def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
|
||||
update = Update(randint(1, 100))
|
||||
@@ -183,7 +179,6 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
|
||||
default_conf['telegram']['enabled'] = False
|
||||
default_conf['telegram']['chat_id'] = 123
|
||||
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -206,6 +201,10 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
|
||||
'amount': 90.99181074,
|
||||
'close_profit': None,
|
||||
'current_profit': -0.59,
|
||||
'initial_stop_loss': 1.098e-05,
|
||||
'stop_loss': 1.099e-05,
|
||||
'initial_stop_loss_pct': -0.05,
|
||||
'stop_loss_pct': -0.01,
|
||||
'open_order': '(limit buy rem=0.00000000)'
|
||||
}]),
|
||||
_status_table=status_table,
|
||||
@@ -232,7 +231,6 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
|
||||
|
||||
|
||||
def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -274,12 +272,18 @@ def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> No
|
||||
# Trigger status while we have a fulfilled order for the open trade
|
||||
telegram._status(bot=MagicMock(), update=update)
|
||||
|
||||
# close_rate should not be included in the message as the trade is not closed
|
||||
# and no line should be empty
|
||||
lines = msg_mock.call_args_list[0][0][0].split('\n')
|
||||
assert '' not in lines
|
||||
assert 'Close Rate' not in ''.join(lines)
|
||||
assert 'Close Profit' not in ''.join(lines)
|
||||
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'ETH/BTC' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -333,7 +337,6 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
|
||||
|
||||
def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
patch_exchange(mocker)
|
||||
mocker.patch(
|
||||
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
|
||||
@@ -405,7 +408,6 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
|
||||
|
||||
def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
patch_exchange(mocker)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -442,7 +444,6 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
|
||||
def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
limit_buy_order, limit_sell_order, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
mocker.patch.multiple(
|
||||
@@ -548,7 +549,6 @@ def test_telegram_balance_handle(default_conf, update, mocker) -> None:
|
||||
'last': 0.1,
|
||||
}
|
||||
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=mock_balance)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_ticker', side_effect=mock_ticker)
|
||||
|
||||
@@ -635,7 +635,6 @@ def test_start_handle_already_running(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_stop_handle(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -655,7 +654,6 @@ def test_stop_handle(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_stop_handle_already_stopped(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -675,7 +673,6 @@ def test_stop_handle_already_stopped(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_stopbuy_handle(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -695,7 +692,6 @@ def test_stopbuy_handle(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_reload_conf_handle(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -716,7 +712,6 @@ def test_reload_conf_handle(default_conf, update, mocker) -> None:
|
||||
|
||||
def test_forcesell_handle(default_conf, update, ticker, fee,
|
||||
ticker_sell_up, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
rpc_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
@@ -767,7 +762,6 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
|
||||
|
||||
def test_forcesell_down_handle(default_conf, update, ticker, fee,
|
||||
ticker_sell_down, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
||||
return_value=15000.0)
|
||||
rpc_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
|
||||
@@ -822,7 +816,6 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
|
||||
|
||||
|
||||
def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
||||
return_value=15000.0)
|
||||
@@ -869,7 +862,6 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker
|
||||
|
||||
|
||||
def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
||||
return_value=15000.0)
|
||||
msg_mock = MagicMock()
|
||||
@@ -910,7 +902,6 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_forcebuy_handle(default_conf, update, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._send_msg', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
@@ -948,7 +939,6 @@ def test_forcebuy_handle(default_conf, update, markets, mocker) -> None:
|
||||
|
||||
|
||||
def test_forcebuy_handle_exception(default_conf, update, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
rpc_mock = mocker.patch('freqtrade.rpc.telegram.Telegram._send_msg', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
@@ -973,7 +963,6 @@ def test_forcebuy_handle_exception(default_conf, update, markets, mocker) -> Non
|
||||
|
||||
def test_performance_handle(default_conf, update, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
@@ -1015,7 +1004,6 @@ def test_performance_handle(default_conf, update, ticker, fee,
|
||||
|
||||
|
||||
def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
@@ -1058,7 +1046,6 @@ def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> Non
|
||||
|
||||
|
||||
def test_whitelist_static(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -1076,7 +1063,6 @@ def test_whitelist_static(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_whitelist_dynamic(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -1098,7 +1084,6 @@ def test_whitelist_dynamic(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_blacklist_static(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -1123,7 +1108,6 @@ def test_blacklist_static(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_edge_disabled(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -1141,7 +1125,6 @@ def test_edge_disabled(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_edge_enabled(edge_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch('freqtrade.edge.Edge._cached_pairs', mocker.PropertyMock(
|
||||
return_value={
|
||||
@@ -1165,7 +1148,6 @@ def test_edge_enabled(edge_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_help_handle(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -1182,7 +1164,6 @@ def test_help_handle(default_conf, update, mocker) -> None:
|
||||
|
||||
|
||||
def test_version_handle(default_conf, update, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
@@ -1409,7 +1390,6 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:
|
||||
|
||||
|
||||
def test__send_msg(default_conf, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
bot = MagicMock()
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
@@ -1421,7 +1401,6 @@ def test__send_msg(default_conf, mocker) -> None:
|
||||
|
||||
|
||||
def test__send_msg_network_error(default_conf, mocker, caplog) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
bot = MagicMock()
|
||||
bot.send_message = MagicMock(side_effect=NetworkError('Oh snap'))
|
||||
|
@@ -5,6 +5,7 @@ import logging
|
||||
from argparse import Namespace
|
||||
from copy import deepcopy
|
||||
from unittest.mock import MagicMock
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from jsonschema import Draft4Validator, ValidationError, validate
|
||||
@@ -547,6 +548,23 @@ def test_set_loggers() -> None:
|
||||
assert logging.getLogger('telegram').level is logging.INFO
|
||||
|
||||
|
||||
def test_set_logfile(default_conf, mocker):
|
||||
mocker.patch('freqtrade.configuration.open',
|
||||
mocker.mock_open(read_data=json.dumps(default_conf)))
|
||||
|
||||
arglist = [
|
||||
'--logfile', 'test_file.log',
|
||||
]
|
||||
args = Arguments(arglist, '').get_parsed_arg()
|
||||
configuration = Configuration(args)
|
||||
validated_conf = configuration.load_config()
|
||||
|
||||
assert validated_conf['logfile'] == "test_file.log"
|
||||
f = Path("test_file.log")
|
||||
assert f.is_file()
|
||||
f.unlink()
|
||||
|
||||
|
||||
def test_load_config_warn_forcebuy(default_conf, mocker, caplog) -> None:
|
||||
default_conf['forcebuy_enable'] = True
|
||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||
|
@@ -1062,6 +1062,13 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
|
||||
assert trade.stoploss_order_id is None
|
||||
assert trade.is_open is False
|
||||
|
||||
mocker.patch(
|
||||
'freqtrade.exchange.Exchange.stoploss_limit',
|
||||
side_effect=DependencyException()
|
||||
)
|
||||
freqtrade.handle_stoploss_on_exchange(trade)
|
||||
assert log_has('Unable to create stoploss order: ', caplog.record_tuples)
|
||||
|
||||
|
||||
def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
|
||||
markets, limit_buy_order, limit_sell_order) -> None:
|
||||
@@ -1312,17 +1319,84 @@ def test_process_maybe_execute_sell(mocker, default_conf, limit_buy_order, caplo
|
||||
# test amount modified by fee-logic
|
||||
assert not freqtrade.process_maybe_execute_sell(trade)
|
||||
|
||||
|
||||
def test_process_maybe_execute_sell_exception(mocker, default_conf,
|
||||
limit_buy_order, caplog) -> None:
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_order', return_value=limit_buy_order)
|
||||
|
||||
trade = MagicMock()
|
||||
trade.open_order_id = '123'
|
||||
trade.open_fee = 0.001
|
||||
|
||||
# Test raise of DependencyException exception
|
||||
mocker.patch(
|
||||
'freqtrade.freqtradebot.FreqtradeBot.update_trade_state',
|
||||
side_effect=DependencyException()
|
||||
)
|
||||
freqtrade.process_maybe_execute_sell(trade)
|
||||
assert log_has('Unable to sell trade: ', caplog.record_tuples)
|
||||
|
||||
|
||||
def test_update_trade_state(mocker, default_conf, limit_buy_order, caplog) -> None:
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
|
||||
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_order', return_value=limit_buy_order)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
|
||||
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
|
||||
return_value=limit_buy_order['amount'])
|
||||
|
||||
trade = Trade()
|
||||
# Mock session away
|
||||
Trade.session = MagicMock()
|
||||
trade.open_order_id = '123'
|
||||
trade.open_fee = 0.001
|
||||
freqtrade.update_trade_state(trade)
|
||||
# Test amount not modified by fee-logic
|
||||
assert not log_has_re(r'Applying fee to .*', caplog.record_tuples)
|
||||
assert trade.open_order_id is None
|
||||
assert trade.amount == limit_buy_order['amount']
|
||||
|
||||
trade.open_order_id = '123'
|
||||
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=90.81)
|
||||
assert trade.amount != 90.81
|
||||
# test amount modified by fee-logic
|
||||
freqtrade.update_trade_state(trade)
|
||||
assert trade.amount == 90.81
|
||||
assert trade.open_order_id is None
|
||||
|
||||
trade.is_open = True
|
||||
trade.open_order_id = None
|
||||
# Assert we call handle_trade() if trade is feasible for execution
|
||||
assert freqtrade.process_maybe_execute_sell(trade)
|
||||
freqtrade.update_trade_state(trade)
|
||||
|
||||
regexp = re.compile('Found open order for.*')
|
||||
assert filter(regexp.match, caplog.record_tuples)
|
||||
|
||||
|
||||
def test_process_maybe_execute_sell_exception(mocker, default_conf,
|
||||
limit_buy_order, caplog) -> None:
|
||||
def test_update_trade_state_withorderdict(default_conf, trades_for_order, limit_buy_order, mocker):
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order)
|
||||
# get_order should not be called!!
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_order', MagicMock(side_effect=ValueError))
|
||||
patch_exchange(mocker)
|
||||
Trade.session = MagicMock()
|
||||
amount = sum(x['amount'] for x in trades_for_order)
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
trade = Trade(
|
||||
pair='LTC/ETH',
|
||||
amount=amount,
|
||||
exchange='binance',
|
||||
open_rate=0.245441,
|
||||
open_order_id="123456"
|
||||
)
|
||||
freqtrade.update_trade_state(trade, limit_buy_order)
|
||||
assert trade.amount != amount
|
||||
assert trade.amount == limit_buy_order['amount']
|
||||
|
||||
|
||||
def test_update_trade_state_exception(mocker, default_conf,
|
||||
limit_buy_order, caplog) -> None:
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_order', return_value=limit_buy_order)
|
||||
|
||||
@@ -1335,17 +1409,9 @@ def test_process_maybe_execute_sell_exception(mocker, default_conf,
|
||||
'freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
|
||||
side_effect=OperationalException()
|
||||
)
|
||||
freqtrade.process_maybe_execute_sell(trade)
|
||||
freqtrade.update_trade_state(trade)
|
||||
assert log_has('Could not update trade amount: ', caplog.record_tuples)
|
||||
|
||||
# Test raise of DependencyException exception
|
||||
mocker.patch(
|
||||
'freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
|
||||
side_effect=DependencyException()
|
||||
)
|
||||
freqtrade.process_maybe_execute_sell(trade)
|
||||
assert log_has('Unable to sell trade: ', caplog.record_tuples)
|
||||
|
||||
|
||||
def test_handle_trade(default_conf, limit_buy_order, limit_sell_order,
|
||||
fee, markets, mocker) -> None:
|
||||
@@ -2296,9 +2362,8 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, market
|
||||
}
|
||||
freqtrade = FreqtradeBot(default_conf)
|
||||
patch_get_signal(freqtrade)
|
||||
freqtrade.strategy.stop_loss_reached = \
|
||||
lambda current_rate, trade, current_time, force_stoploss, current_profit: SellCheckTuple(
|
||||
sell_flag=False, sell_type=SellType.NONE)
|
||||
freqtrade.strategy.stop_loss_reached = MagicMock(return_value=SellCheckTuple(
|
||||
sell_flag=False, sell_type=SellType.NONE))
|
||||
freqtrade.create_trade()
|
||||
|
||||
trade = Trade.query.first()
|
||||
@@ -2444,8 +2509,7 @@ def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets
|
||||
}))
|
||||
# stop-loss not reached, adjusted stoploss
|
||||
assert freqtrade.handle_trade(trade) is False
|
||||
assert log_has(f'using positive stop loss mode: 0.01 with offset 0 '
|
||||
f'since we have profit 0.2666%',
|
||||
assert log_has(f'using positive stop loss: 0.01 offset: 0 profit: 0.2666%',
|
||||
caplog.record_tuples)
|
||||
assert log_has(f'adjusted stop loss', caplog.record_tuples)
|
||||
assert trade.stop_loss == 0.0000138501
|
||||
@@ -2504,8 +2568,7 @@ def test_trailing_stop_loss_offset(default_conf, limit_buy_order, fee,
|
||||
}))
|
||||
# stop-loss not reached, adjusted stoploss
|
||||
assert freqtrade.handle_trade(trade) is False
|
||||
assert log_has(f'using positive stop loss mode: 0.01 with offset 0.011 '
|
||||
f'since we have profit 0.2666%',
|
||||
assert log_has(f'using positive stop loss: 0.01 offset: 0.011 profit: 0.2666%',
|
||||
caplog.record_tuples)
|
||||
assert log_has(f'adjusted stop loss', caplog.record_tuples)
|
||||
assert trade.stop_loss == 0.0000138501
|
||||
@@ -2584,8 +2647,7 @@ def test_tsl_only_offset_reached(default_conf, limit_buy_order, fee,
|
||||
}))
|
||||
|
||||
assert freqtrade.handle_trade(trade) is False
|
||||
assert log_has(f'using positive stop loss mode: 0.05 with offset 0.055 '
|
||||
f'since we have profit 0.1218%',
|
||||
assert log_has(f'using positive stop loss: 0.05 offset: 0.055 profit: 0.1218%',
|
||||
caplog.record_tuples)
|
||||
assert log_has(f'adjusted stop loss', caplog.record_tuples)
|
||||
assert trade.stop_loss == 0.0000117705
|
||||
|
@@ -510,6 +510,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog):
|
||||
assert trade.pair == "ETC/BTC"
|
||||
assert trade.exchange == "binance"
|
||||
assert trade.max_rate == 0.0
|
||||
assert trade.min_rate is None
|
||||
assert trade.stop_loss == 0.0
|
||||
assert trade.initial_stop_loss == 0.0
|
||||
assert trade.sell_reason is None
|
||||
@@ -585,7 +586,58 @@ def test_migrate_mid_state(mocker, default_conf, fee, caplog):
|
||||
caplog.record_tuples)
|
||||
|
||||
|
||||
def test_adjust_stop_loss(limit_buy_order, limit_sell_order, fee):
|
||||
def test_adjust_stop_loss(fee):
|
||||
trade = Trade(
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
fee_open=fee.return_value,
|
||||
fee_close=fee.return_value,
|
||||
exchange='bittrex',
|
||||
open_rate=1,
|
||||
max_rate=1,
|
||||
)
|
||||
|
||||
trade.adjust_stop_loss(trade.open_rate, 0.05, True)
|
||||
assert trade.stop_loss == 0.95
|
||||
assert trade.stop_loss_pct == -0.05
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.initial_stop_loss_pct == -0.05
|
||||
|
||||
# Get percent of profit with a lower rate
|
||||
trade.adjust_stop_loss(0.96, 0.05)
|
||||
assert trade.stop_loss == 0.95
|
||||
assert trade.stop_loss_pct == -0.05
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.initial_stop_loss_pct == -0.05
|
||||
|
||||
# Get percent of profit with a custom rate (Higher than open rate)
|
||||
trade.adjust_stop_loss(1.3, -0.1)
|
||||
assert round(trade.stop_loss, 8) == 1.17
|
||||
assert trade.stop_loss_pct == -0.1
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.initial_stop_loss_pct == -0.05
|
||||
|
||||
# current rate lower again ... should not change
|
||||
trade.adjust_stop_loss(1.2, 0.1)
|
||||
assert round(trade.stop_loss, 8) == 1.17
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.initial_stop_loss_pct == -0.05
|
||||
|
||||
# current rate higher... should raise stoploss
|
||||
trade.adjust_stop_loss(1.4, 0.1)
|
||||
assert round(trade.stop_loss, 8) == 1.26
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.initial_stop_loss_pct == -0.05
|
||||
|
||||
# Initial is true but stop_loss set - so doesn't do anything
|
||||
trade.adjust_stop_loss(1.7, 0.1, True)
|
||||
assert round(trade.stop_loss, 8) == 1.26
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.initial_stop_loss_pct == -0.05
|
||||
assert trade.stop_loss_pct == -0.1
|
||||
|
||||
|
||||
def test_adjust_min_max_rates(fee):
|
||||
trade = Trade(
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
@@ -595,40 +647,24 @@ def test_adjust_stop_loss(limit_buy_order, limit_sell_order, fee):
|
||||
open_rate=1,
|
||||
)
|
||||
|
||||
trade.adjust_stop_loss(trade.open_rate, 0.05, True)
|
||||
assert trade.stop_loss == 0.95
|
||||
trade.adjust_min_max_rates(trade.open_rate)
|
||||
assert trade.max_rate == 1
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.min_rate == 1
|
||||
|
||||
# Get percent of profit with a lowre rate
|
||||
trade.adjust_stop_loss(0.96, 0.05)
|
||||
assert trade.stop_loss == 0.95
|
||||
# check min adjusted, max remained
|
||||
trade.adjust_min_max_rates(0.96)
|
||||
assert trade.max_rate == 1
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
assert trade.min_rate == 0.96
|
||||
|
||||
# Get percent of profit with a custom rate (Higher than open rate)
|
||||
trade.adjust_stop_loss(1.3, -0.1)
|
||||
assert round(trade.stop_loss, 8) == 1.17
|
||||
assert trade.max_rate == 1.3
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
# check max adjusted, min remains
|
||||
trade.adjust_min_max_rates(1.05)
|
||||
assert trade.max_rate == 1.05
|
||||
assert trade.min_rate == 0.96
|
||||
|
||||
# current rate lower again ... should not change
|
||||
trade.adjust_stop_loss(1.2, 0.1)
|
||||
assert round(trade.stop_loss, 8) == 1.17
|
||||
assert trade.max_rate == 1.3
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
|
||||
# current rate higher... should raise stoploss
|
||||
trade.adjust_stop_loss(1.4, 0.1)
|
||||
assert round(trade.stop_loss, 8) == 1.26
|
||||
assert trade.max_rate == 1.4
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
|
||||
# Initial is true but stop_loss set - so doesn't do anything
|
||||
trade.adjust_stop_loss(1.7, 0.1, True)
|
||||
assert round(trade.stop_loss, 8) == 1.26
|
||||
assert trade.max_rate == 1.4
|
||||
assert trade.initial_stop_loss == 0.95
|
||||
# current rate "in the middle" - no adjustment
|
||||
trade.adjust_min_max_rates(1.03)
|
||||
assert trade.max_rate == 1.05
|
||||
assert trade.min_rate == 0.96
|
||||
|
||||
|
||||
def test_get_open(default_conf, fee):
|
||||
|
Reference in New Issue
Block a user