Merge branch 'develop' into feat/short

This commit is contained in:
Sam Germain 2021-10-03 02:12:25 -06:00
commit d3f7207fe6
10 changed files with 1395 additions and 1025 deletions

View File

@ -109,6 +109,7 @@ All freqtrade arguments will be available by running `docker-compose run --rm fr
!!! Warning "`docker-compose` for trade commands" !!! Warning "`docker-compose` for trade commands"
Trade commands (`freqtrade trade <...>`) should not be ran via `docker-compose run` - but should use `docker-compose up -d` instead. Trade commands (`freqtrade trade <...>`) should not be ran via `docker-compose run` - but should use `docker-compose up -d` instead.
This makes sure that the container is properly started (including port forwardings) and will make sure that the container will restart after a system reboot. This makes sure that the container is properly started (including port forwardings) and will make sure that the container will restart after a system reboot.
If you intend to use freqUI, please also ensure to adjust the [configuration accordingly](rest-api.md#configuration-with-docker), otherwise the UI will not be available.
!!! Note "`docker-compose run --rm`" !!! Note "`docker-compose run --rm`"
Including `--rm` will remove the container after completion, and is highly recommended for all modes except trading mode (running with `freqtrade trade` command). Including `--rm` will remove the container after completion, and is highly recommended for all modes except trading mode (running with `freqtrade trade` command).

View File

@ -27,7 +27,8 @@ from freqtrade.resolvers import ExchangeResolver
from freqtrade.worker import Worker from freqtrade.worker import Worker
from tests.conftest_trades import (leverage_trade, mock_trade_1, mock_trade_2, mock_trade_3, from tests.conftest_trades import (leverage_trade, mock_trade_1, mock_trade_2, mock_trade_3,
mock_trade_4, mock_trade_5, mock_trade_6, short_trade) mock_trade_4, mock_trade_5, mock_trade_6, short_trade)
from tests.conftest_trades_usdt import (mock_trade_usdt_1, mock_trade_usdt_2, mock_trade_usdt_3,
mock_trade_usdt_4, mock_trade_usdt_5, mock_trade_usdt_6)
logging.getLogger('').setLevel(logging.INFO) logging.getLogger('').setLevel(logging.INFO)
@ -281,6 +282,7 @@ def create_mock_trades_with_leverage(fee, use_db: bool = True):
Trade.query.session.add(trade) Trade.query.session.add(trade)
else: else:
LocalTrade.add_bt_trade(trade) LocalTrade.add_bt_trade(trade)
# Simulate dry_run entries # Simulate dry_run entries
trade = mock_trade_1(fee) trade = mock_trade_1(fee)
add_trade(trade) add_trade(trade)
@ -305,6 +307,40 @@ def create_mock_trades_with_leverage(fee, use_db: bool = True):
trade = leverage_trade(fee) trade = leverage_trade(fee)
add_trade(trade) add_trade(trade)
if use_db:
Trade.query.session.flush()
def create_mock_trades_usdt(fee, use_db: bool = True):
"""
Create some fake trades ...
"""
def add_trade(trade):
if use_db:
Trade.query.session.add(trade)
else:
LocalTrade.add_bt_trade(trade)
# Simulate dry_run entries
trade = mock_trade_usdt_1(fee)
add_trade(trade)
trade = mock_trade_usdt_2(fee)
add_trade(trade)
trade = mock_trade_usdt_3(fee)
add_trade(trade)
trade = mock_trade_usdt_4(fee)
add_trade(trade)
trade = mock_trade_usdt_5(fee)
add_trade(trade)
trade = mock_trade_usdt_6(fee)
add_trade(trade)
if use_db: if use_db:
Trade.query.session.flush() Trade.query.session.flush()
@ -345,6 +381,11 @@ def default_conf(testdatadir):
return get_default_conf(testdatadir) return get_default_conf(testdatadir)
@pytest.fixture(scope="function")
def default_conf_usdt(testdatadir):
return get_default_conf_usdt(testdatadir)
def get_default_conf(testdatadir): def get_default_conf(testdatadir):
""" Returns validated configuration suitable for most tests """ """ Returns validated configuration suitable for most tests """
configuration = { configuration = {
@ -419,6 +460,32 @@ def get_default_conf(testdatadir):
return configuration return configuration
def get_default_conf_usdt(testdatadir):
configuration = get_default_conf(testdatadir)
configuration.update({
"stake_amount": 60.0,
"stake_currency": "USDT",
"exchange": {
"name": "binance",
"enabled": True,
"key": "key",
"secret": "secret",
"pair_whitelist": [
"ETH/USDT",
"LTC/USDT",
"XRP/USDT",
"NEO/USDT",
"TKN/USDT",
],
"pair_blacklist": [
"DOGE/USDT",
"HOT/USDT",
]
},
})
return configuration
@pytest.fixture @pytest.fixture
def update(): def update():
_update = Update(0) _update = Update(0)
@ -458,6 +525,33 @@ def ticker_sell_down():
}) })
@pytest.fixture
def ticker_usdt():
return MagicMock(return_value={
'bid': 2.0,
'ask': 2.02,
'last': 2.0,
})
@pytest.fixture
def ticker_usdt_sell_up():
return MagicMock(return_value={
'bid': 2.2,
'ask': 2.3,
'last': 2.2,
})
@pytest.fixture
def ticker_usdt_sell_down():
return MagicMock(return_value={
'bid': 2.01,
'ask': 2.0,
'last': 2.01,
})
@pytest.fixture @pytest.fixture
def markets(): def markets():
return get_markets() return get_markets()
@ -705,6 +799,81 @@ def get_markets():
}, },
'info': {}, 'info': {},
}, },
'XRP/USDT': {
'id': 'xrpusdt',
'symbol': 'XRP/USDT',
'base': 'XRP',
'quote': 'USDT',
'active': True,
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': {
'min': 0.0001,
'max': 500000,
},
},
'info': {},
},
'NEO/USDT': {
'id': 'neousdt',
'symbol': 'NEO/USDT',
'base': 'NEO',
'quote': 'USDT',
'active': True,
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': {
'min': 0.0001,
'max': 500000,
},
},
'info': {},
},
'TKN/USDT': {
'id': 'tknusdt',
'symbol': 'TKN/USDT',
'base': 'TKN',
'quote': 'USDT',
'active': True,
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': {
'min': 0.0001,
'max': 500000,
},
},
'info': {},
},
'LTC/USD': { 'LTC/USD': {
'id': 'USD-LTC', 'id': 'USD-LTC',
'symbol': 'LTC/USD', 'symbol': 'LTC/USD',
@ -1639,27 +1808,34 @@ def result(testdatadir):
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def trades_for_order(): def trades_for_order():
return [{'info': {'id': 34567, return [{
'info': {
'id': 34567,
'orderId': 123456, 'orderId': 123456,
'price': '0.24544100', 'price': '2.0',
'qty': '8.00000000', 'qty': '8.00000000',
'commission': '0.00800000', 'commission': '0.00800000',
'commissionAsset': 'LTC', 'commissionAsset': 'LTC',
'time': 1521663363189, 'time': 1521663363189,
'isBuyer': True, 'isBuyer': True,
'isMaker': False, 'isMaker': False,
'isBestMatch': True}, 'isBestMatch': True
},
'timestamp': 1521663363189, 'timestamp': 1521663363189,
'datetime': '2018-03-21T20:16:03.189Z', 'datetime': '2018-03-21T20:16:03.189Z',
'symbol': 'LTC/ETH', 'symbol': 'LTC/USDT',
'id': '34567', 'id': '34567',
'order': '123456', 'order': '123456',
'type': None, 'type': None,
'side': 'buy', 'side': 'buy',
'price': 0.245441, 'price': 2.0,
'cost': 1.963528, 'cost': 16.0,
'amount': 8.0, 'amount': 8.0,
'fee': {'cost': 0.008, 'currency': 'LTC'}}] 'fee': {
'cost': 0.008,
'currency': 'LTC'
}
}]
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
@ -1924,6 +2100,22 @@ def open_trade():
) )
@pytest.fixture(scope="function")
def open_trade_usdt():
return Trade(
pair='ADA/USDT',
open_rate=2.0,
exchange='binance',
open_order_id='123456789',
amount=30.0,
fee_open=0.0,
fee_close=0.0,
stake_amount=60.0,
open_date=arrow.utcnow().shift(minutes=-601).datetime,
is_open=True
)
@pytest.fixture @pytest.fixture
def saved_hyperopt_results(): def saved_hyperopt_results():
hyperopt_res = [ hyperopt_res = [
@ -2067,7 +2259,7 @@ def saved_hyperopt_results():
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def limit_buy_order_usdt_open(): def limit_buy_order_usdt_open():
return { return {
'id': 'mocked_limit_buy', 'id': 'mocked_limit_buy_usdt',
'type': 'limit', 'type': 'limit',
'side': 'buy', 'side': 'buy',
'symbol': 'mocked', 'symbol': 'mocked',
@ -2094,7 +2286,7 @@ def limit_buy_order_usdt(limit_buy_order_usdt_open):
@pytest.fixture @pytest.fixture
def limit_sell_order_usdt_open(): def limit_sell_order_usdt_open():
return { return {
'id': 'mocked_limit_sell', 'id': 'mocked_limit_sell_usdt',
'type': 'limit', 'type': 'limit',
'side': 'sell', 'side': 'sell',
'pair': 'mocked', 'pair': 'mocked',

View File

@ -0,0 +1,305 @@
from datetime import datetime, timedelta, timezone
from freqtrade.persistence.models import Order, Trade
MOCK_TRADE_COUNT = 6
def mock_order_usdt_1():
return {
'id': '1234',
'symbol': 'ADA/USDT',
'status': 'closed',
'side': 'buy',
'type': 'limit',
'price': 2.0,
'amount': 10.0,
'filled': 10.0,
'remaining': 0.0,
}
def mock_trade_usdt_1(fee):
trade = Trade(
pair='ADA/USDT',
stake_amount=20.0,
amount=10.0,
amount_requested=10.0,
fee_open=fee.return_value,
fee_close=fee.return_value,
is_open=True,
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=17),
open_rate=2.0,
exchange='binance',
open_order_id='dry_run_buy_12345',
strategy='StrategyTestV2',
timeframe=5,
)
o = Order.parse_from_ccxt_object(mock_order_usdt_1(), 'ADA/USDT', 'buy')
trade.orders.append(o)
return trade
def mock_order_usdt_2():
return {
'id': '1235',
'symbol': 'ETC/USDT',
'status': 'closed',
'side': 'buy',
'type': 'limit',
'price': 2.0,
'amount': 100.0,
'filled': 100.0,
'remaining': 0.0,
}
def mock_order_usdt_2_sell():
return {
'id': '12366',
'symbol': 'ETC/USDT',
'status': 'closed',
'side': 'sell',
'type': 'limit',
'price': 2.05,
'amount': 100.0,
'filled': 100.0,
'remaining': 0.0,
}
def mock_trade_usdt_2(fee):
"""
Closed trade...
"""
trade = Trade(
pair='ETC/USDT',
stake_amount=200.0,
amount=100.0,
amount_requested=100.0,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_rate=2.0,
close_rate=2.05,
close_profit=5.0,
close_profit_abs=3.9875,
exchange='binance',
is_open=False,
open_order_id='dry_run_sell_12345',
strategy='StrategyTestV2',
timeframe=5,
sell_reason='sell_signal',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
)
o = Order.parse_from_ccxt_object(mock_order_usdt_2(), 'ETC/USDT', 'buy')
trade.orders.append(o)
o = Order.parse_from_ccxt_object(mock_order_usdt_2_sell(), 'ETC/USDT', 'sell')
trade.orders.append(o)
return trade
def mock_order_usdt_3():
return {
'id': '41231a12a',
'symbol': 'XRP/USDT',
'status': 'closed',
'side': 'buy',
'type': 'limit',
'price': 1.0,
'amount': 30.0,
'filled': 30.0,
'remaining': 0.0,
}
def mock_order_usdt_3_sell():
return {
'id': '41231a666a',
'symbol': 'XRP/USDT',
'status': 'closed',
'side': 'sell',
'type': 'stop_loss_limit',
'price': 1.1,
'average': 1.1,
'amount': 30.0,
'filled': 30.0,
'remaining': 0.0,
}
def mock_trade_usdt_3(fee):
"""
Closed trade
"""
trade = Trade(
pair='XRP/USDT',
stake_amount=30.0,
amount=30.0,
amount_requested=30.0,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_rate=1.0,
close_rate=1.1,
close_profit=10.0,
close_profit_abs=9.8425,
exchange='binance',
is_open=False,
strategy='StrategyTestV2',
timeframe=5,
sell_reason='roi',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
close_date=datetime.now(tz=timezone.utc),
)
o = Order.parse_from_ccxt_object(mock_order_usdt_3(), 'XRP/USDT', 'buy')
trade.orders.append(o)
o = Order.parse_from_ccxt_object(mock_order_usdt_3_sell(), 'XRP/USDT', 'sell')
trade.orders.append(o)
return trade
def mock_order_usdt_4():
return {
'id': 'prod_buy_12345',
'symbol': 'ETC/USDT',
'status': 'open',
'side': 'buy',
'type': 'limit',
'price': 2.0,
'amount': 10.0,
'filled': 0.0,
'remaining': 30.0,
}
def mock_trade_usdt_4(fee):
"""
Simulate prod entry
"""
trade = Trade(
pair='ETC/USDT',
stake_amount=20.0,
amount=10.0,
amount_requested=10.01,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=14),
is_open=True,
open_rate=2.0,
exchange='binance',
open_order_id='prod_buy_12345',
strategy='StrategyTestV2',
timeframe=5,
)
o = Order.parse_from_ccxt_object(mock_order_usdt_4(), 'ETC/USDT', 'buy')
trade.orders.append(o)
return trade
def mock_order_usdt_5():
return {
'id': 'prod_buy_3455',
'symbol': 'XRP/USDT',
'status': 'closed',
'side': 'buy',
'type': 'limit',
'price': 2.0,
'amount': 10.0,
'filled': 10.0,
'remaining': 0.0,
}
def mock_order_usdt_5_stoploss():
return {
'id': 'prod_stoploss_3455',
'symbol': 'XRP/USDT',
'status': 'open',
'side': 'sell',
'type': 'stop_loss_limit',
'price': 2.0,
'amount': 10.0,
'filled': 0.0,
'remaining': 30.0,
}
def mock_trade_usdt_5(fee):
"""
Simulate prod entry with stoploss
"""
trade = Trade(
pair='XRP/USDT',
stake_amount=20.0,
amount=10.0,
amount_requested=10.01,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=12),
is_open=True,
open_rate=2.0,
exchange='binance',
strategy='SampleStrategy',
stoploss_order_id='prod_stoploss_3455',
timeframe=5,
)
o = Order.parse_from_ccxt_object(mock_order_usdt_5(), 'XRP/USDT', 'buy')
trade.orders.append(o)
o = Order.parse_from_ccxt_object(mock_order_usdt_5_stoploss(), 'XRP/USDT', 'stoploss')
trade.orders.append(o)
return trade
def mock_order_usdt_6():
return {
'id': 'prod_buy_6',
'symbol': 'LTC/USDT',
'status': 'closed',
'side': 'buy',
'type': 'limit',
'price': 10.0,
'amount': 2.0,
'filled': 2.0,
'remaining': 0.0,
}
def mock_order_usdt_6_sell():
return {
'id': 'prod_sell_6',
'symbol': 'LTC/USDT',
'status': 'open',
'side': 'sell',
'type': 'limit',
'price': 12.0,
'amount': 2.0,
'filled': 0.0,
'remaining': 2.0,
}
def mock_trade_usdt_6(fee):
"""
Simulate prod entry with open sell order
"""
trade = Trade(
pair='LTC/USDT',
stake_amount=20.0,
amount=2.0,
amount_requested=2.0,
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
fee_open=fee.return_value,
fee_close=fee.return_value,
is_open=True,
open_rate=10.0,
exchange='binance',
strategy='SampleStrategy',
open_order_id="prod_sell_6",
timeframe=5,
)
o = Order.parse_from_ccxt_object(mock_order_usdt_6(), 'LTC/USDT', 'buy')
trade.orders.append(o)
o = Order.parse_from_ccxt_object(mock_order_usdt_6_sell(), 'LTC/USDT', 'sell')
trade.orders.append(o)
return trade

View File

@ -327,5 +327,8 @@ def test_fill_leverage_brackets_kraken(default_conf, mocker):
'LTC/USDT': [1], 'LTC/USDT': [1],
'LTC/USD': [1], 'LTC/USD': [1],
'XLTCUSDT': [1], 'XLTCUSDT': [1],
'LTC/ETH': [1] 'LTC/ETH': [1],
'NEO/USDT': [1],
'TKN/USDT': [1],
'XRP/USDT': [1]
} }

View File

@ -39,16 +39,25 @@ def hyperopt(hyperopt_conf, mocker):
def hyperopt_results(): def hyperopt_results():
return pd.DataFrame( return pd.DataFrame(
{ {
'pair': ['ETH/BTC', 'ETH/BTC', 'ETH/BTC'], 'pair': ['ETH/USDT', 'ETH/USDT', 'ETH/USDT', 'ETH/USDT'],
'profit_ratio': [-0.1, 0.2, 0.3], 'profit_ratio': [-0.1, 0.2, -0.1, 0.3],
'profit_abs': [-0.2, 0.4, 0.6], 'profit_abs': [-0.2, 0.4, -0.2, 0.6],
'trade_duration': [10, 30, 10], 'trade_duration': [10, 30, 10, 10],
'sell_reason': [SellType.STOP_LOSS, SellType.ROI, SellType.ROI], 'amount': [0.1, 0.1, 0.1, 0.1],
'sell_reason': [SellType.STOP_LOSS, SellType.ROI, SellType.STOP_LOSS, SellType.ROI],
'open_date':
[
datetime(2019, 1, 1, 9, 15, 0),
datetime(2019, 1, 2, 8, 55, 0),
datetime(2019, 1, 3, 9, 15, 0),
datetime(2019, 1, 4, 9, 15, 0),
],
'close_date': 'close_date':
[ [
datetime(2019, 1, 1, 9, 26, 3, 478039), datetime(2019, 1, 1, 9, 25, 0),
datetime(2019, 2, 1, 9, 26, 3, 478039), datetime(2019, 1, 2, 9, 25, 0),
datetime(2019, 3, 1, 9, 26, 3, 478039) datetime(2019, 1, 3, 9, 25, 0),
] datetime(2019, 1, 4, 9, 25, 0),
],
} }
) )

View File

@ -35,6 +35,7 @@ def test_hyperoptlossresolver_wrongname(default_conf) -> None:
def test_loss_calculation_prefer_correct_trade_count(hyperopt_conf, hyperopt_results) -> None: def test_loss_calculation_prefer_correct_trade_count(hyperopt_conf, hyperopt_results) -> None:
hyperopt_conf.update({'hyperopt_loss': "ShortTradeDurHyperOptLoss"})
hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf) hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf)
correct = hl.hyperopt_loss_function(hyperopt_results, 600, correct = hl.hyperopt_loss_function(hyperopt_results, 600,
datetime(2019, 1, 1), datetime(2019, 5, 1)) datetime(2019, 1, 1), datetime(2019, 5, 1))
@ -50,6 +51,7 @@ def test_loss_calculation_prefer_shorter_trades(hyperopt_conf, hyperopt_results)
resultsb = hyperopt_results.copy() resultsb = hyperopt_results.copy()
resultsb.loc[1, 'trade_duration'] = 20 resultsb.loc[1, 'trade_duration'] = 20
hyperopt_conf.update({'hyperopt_loss': "ShortTradeDurHyperOptLoss"})
hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf) hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf)
longer = hl.hyperopt_loss_function(hyperopt_results, 100, longer = hl.hyperopt_loss_function(hyperopt_results, 100,
datetime(2019, 1, 1), datetime(2019, 5, 1)) datetime(2019, 1, 1), datetime(2019, 5, 1))
@ -64,6 +66,7 @@ def test_loss_calculation_has_limited_profit(hyperopt_conf, hyperopt_results) ->
results_under = hyperopt_results.copy() results_under = hyperopt_results.copy()
results_under['profit_ratio'] = hyperopt_results['profit_ratio'] / 2 results_under['profit_ratio'] = hyperopt_results['profit_ratio'] / 2
hyperopt_conf.update({'hyperopt_loss': "ShortTradeDurHyperOptLoss"})
hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf) hl = HyperOptLossResolver.load_hyperoptloss(hyperopt_conf)
correct = hl.hyperopt_loss_function(hyperopt_results, 600, correct = hl.hyperopt_loss_function(hyperopt_results, 600,
datetime(2019, 1, 1), datetime(2019, 5, 1)) datetime(2019, 1, 1), datetime(2019, 5, 1))
@ -75,91 +78,28 @@ def test_loss_calculation_has_limited_profit(hyperopt_conf, hyperopt_results) ->
assert under > correct assert under > correct
def test_sharpe_loss_prefers_higher_profits(default_conf, hyperopt_results) -> None: @pytest.mark.parametrize('lossfunction', [
results_over = hyperopt_results.copy() "OnlyProfitHyperOptLoss",
results_over['profit_ratio'] = hyperopt_results['profit_ratio'] * 2 "SortinoHyperOptLoss",
results_under = hyperopt_results.copy() "SortinoHyperOptLossDaily",
results_under['profit_ratio'] = hyperopt_results['profit_ratio'] / 2 "SharpeHyperOptLoss",
"SharpeHyperOptLossDaily",
default_conf.update({'hyperopt_loss': 'SharpeHyperOptLoss'}) ])
hl = HyperOptLossResolver.load_hyperoptloss(default_conf) def test_loss_functions_better_profits(default_conf, hyperopt_results, lossfunction) -> None:
correct = hl.hyperopt_loss_function(hyperopt_results, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
over = hl.hyperopt_loss_function(results_over, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
under = hl.hyperopt_loss_function(results_under, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
assert over < correct
assert under > correct
def test_sharpe_loss_daily_prefers_higher_profits(default_conf, hyperopt_results) -> None:
results_over = hyperopt_results.copy()
results_over['profit_ratio'] = hyperopt_results['profit_ratio'] * 2
results_under = hyperopt_results.copy()
results_under['profit_ratio'] = hyperopt_results['profit_ratio'] / 2
default_conf.update({'hyperopt_loss': 'SharpeHyperOptLossDaily'})
hl = HyperOptLossResolver.load_hyperoptloss(default_conf)
correct = hl.hyperopt_loss_function(hyperopt_results, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
over = hl.hyperopt_loss_function(results_over, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
under = hl.hyperopt_loss_function(results_under, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
assert over < correct
assert under > correct
def test_sortino_loss_prefers_higher_profits(default_conf, hyperopt_results) -> None:
results_over = hyperopt_results.copy()
results_over['profit_ratio'] = hyperopt_results['profit_ratio'] * 2
results_under = hyperopt_results.copy()
results_under['profit_ratio'] = hyperopt_results['profit_ratio'] / 2
default_conf.update({'hyperopt_loss': 'SortinoHyperOptLoss'})
hl = HyperOptLossResolver.load_hyperoptloss(default_conf)
correct = hl.hyperopt_loss_function(hyperopt_results, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
over = hl.hyperopt_loss_function(results_over, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
under = hl.hyperopt_loss_function(results_under, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
assert over < correct
assert under > correct
def test_sortino_loss_daily_prefers_higher_profits(default_conf, hyperopt_results) -> None:
results_over = hyperopt_results.copy()
results_over['profit_ratio'] = hyperopt_results['profit_ratio'] * 2
results_under = hyperopt_results.copy()
results_under['profit_ratio'] = hyperopt_results['profit_ratio'] / 2
default_conf.update({'hyperopt_loss': 'SortinoHyperOptLossDaily'})
hl = HyperOptLossResolver.load_hyperoptloss(default_conf)
correct = hl.hyperopt_loss_function(hyperopt_results, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
over = hl.hyperopt_loss_function(results_over, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
under = hl.hyperopt_loss_function(results_under, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1))
assert over < correct
assert under > correct
def test_onlyprofit_loss_prefers_higher_profits(default_conf, hyperopt_results) -> None:
results_over = hyperopt_results.copy() results_over = hyperopt_results.copy()
results_over['profit_abs'] = hyperopt_results['profit_abs'] * 2 results_over['profit_abs'] = hyperopt_results['profit_abs'] * 2
results_over['profit_ratio'] = hyperopt_results['profit_ratio'] * 2
results_under = hyperopt_results.copy() results_under = hyperopt_results.copy()
results_under['profit_abs'] = hyperopt_results['profit_abs'] / 2 results_under['profit_abs'] = hyperopt_results['profit_abs'] / 2
results_under['profit_ratio'] = hyperopt_results['profit_ratio'] / 2
default_conf.update({'hyperopt_loss': 'OnlyProfitHyperOptLoss'}) default_conf.update({'hyperopt_loss': lossfunction})
hl = HyperOptLossResolver.load_hyperoptloss(default_conf) hl = HyperOptLossResolver.load_hyperoptloss(default_conf)
correct = hl.hyperopt_loss_function(hyperopt_results, len(hyperopt_results), correct = hl.hyperopt_loss_function(hyperopt_results, len(hyperopt_results),
datetime(2019, 1, 1), datetime(2019, 5, 1)) datetime(2019, 1, 1), datetime(2019, 5, 1))
over = hl.hyperopt_loss_function(results_over, len(hyperopt_results), over = hl.hyperopt_loss_function(results_over, len(results_over),
datetime(2019, 1, 1), datetime(2019, 5, 1)) datetime(2019, 1, 1), datetime(2019, 5, 1))
under = hl.hyperopt_loss_function(results_under, len(hyperopt_results), under = hl.hyperopt_loss_function(results_under, len(results_under),
datetime(2019, 1, 1), datetime(2019, 5, 1)) datetime(2019, 1, 1), datetime(2019, 5, 1))
assert over < correct assert over < correct
assert under > correct assert under > correct

View File

@ -1011,7 +1011,7 @@ def test_rpc_blacklist(mocker, default_conf) -> None:
assert len(ret['blacklist']) == 4 assert len(ret['blacklist']) == 4
assert ret['blacklist'] == default_conf['exchange']['pair_blacklist'] assert ret['blacklist'] == default_conf['exchange']['pair_blacklist']
assert ret['blacklist'] == ['DOGE/BTC', 'HOT/BTC', 'ETH/BTC', 'XRP/.*'] assert ret['blacklist'] == ['DOGE/BTC', 'HOT/BTC', 'ETH/BTC', 'XRP/.*']
assert ret['blacklist_expanded'] == ['ETH/BTC', 'XRP/BTC'] assert ret['blacklist_expanded'] == ['ETH/BTC', 'XRP/BTC', 'XRP/USDT']
assert 'errors' in ret assert 'errors' in ret
assert isinstance(ret['errors'], dict) assert isinstance(ret['errors'], dict)

View File

@ -937,7 +937,7 @@ def test_api_blacklist(botclient, mocker):
data='{"blacklist": ["XRP/.*"]}') data='{"blacklist": ["XRP/.*"]}')
assert_response(rc) assert_response(rc)
assert rc.json() == {"blacklist": ["DOGE/BTC", "HOT/BTC", "ETH/BTC", "XRP/.*"], assert rc.json() == {"blacklist": ["DOGE/BTC", "HOT/BTC", "ETH/BTC", "XRP/.*"],
"blacklist_expanded": ["ETH/BTC", "XRP/BTC"], "blacklist_expanded": ["ETH/BTC", "XRP/BTC", "XRP/USDT"],
"length": 4, "length": 4,
"method": ["StaticPairList"], "method": ["StaticPairList"],
"errors": {}, "errors": {},

View File

@ -9,13 +9,13 @@ from freqtrade.strategy import (merge_informative_pair, stoploss_from_absolute,
timeframe_to_minutes) timeframe_to_minutes)
def generate_test_data(timeframe: str, size: int): def generate_test_data(timeframe: str, size: int, start: str = '2020-07-05'):
np.random.seed(42) np.random.seed(42)
tf_mins = timeframe_to_minutes(timeframe) tf_mins = timeframe_to_minutes(timeframe)
base = np.random.normal(20, 2, size=size) base = np.random.normal(20, 2, size=size)
date = pd.period_range('2020-07-05', periods=size, freq=f'{tf_mins}min').to_timestamp() date = pd.date_range(start, periods=size, freq=f'{tf_mins}min', tz='UTC')
df = pd.DataFrame({ df = pd.DataFrame({
'date': date, 'date': date,
'open': base, 'open': base,

File diff suppressed because it is too large Load Diff