Merge branch 'develop' into add-inlier-metric

This commit is contained in:
Robert Caulk
2022-09-06 20:40:21 +02:00
committed by GitHub
38 changed files with 664 additions and 349 deletions

View File

@@ -1,4 +1,3 @@
from math import isclose
from pathlib import Path
from unittest.mock import MagicMock
@@ -269,7 +268,7 @@ def test_create_cum_profit(testdatadir):
"cum_profits", timeframe="5m")
assert "cum_profits" in cum_profits.columns
assert cum_profits.iloc[0]['cum_profits'] == 0
assert isclose(cum_profits.iloc[-1]['cum_profits'], 8.723007518796964e-06)
assert pytest.approx(cum_profits.iloc[-1]['cum_profits']) == 8.723007518796964e-06
def test_create_cum_profit1(testdatadir):
@@ -287,7 +286,7 @@ def test_create_cum_profit1(testdatadir):
"cum_profits", timeframe="5m")
assert "cum_profits" in cum_profits.columns
assert cum_profits.iloc[0]['cum_profits'] == 0
assert isclose(cum_profits.iloc[-1]['cum_profits'], 8.723007518796964e-06)
assert pytest.approx(cum_profits.iloc[-1]['cum_profits']) == 8.723007518796964e-06
with pytest.raises(ValueError, match='Trade dataframe empty.'):
create_cum_profit(df.set_index('date'), bt_data[bt_data["pair"] == 'NOTAPAIR'],

View File

@@ -2,7 +2,6 @@ import copy
import logging
from copy import deepcopy
from datetime import datetime, timedelta, timezone
from math import isclose
from random import randint
from unittest.mock import MagicMock, Mock, PropertyMock, patch
@@ -407,10 +406,10 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
# min
result = exchange.get_min_pair_stake_amount('ETH/BTC', 1, stoploss)
expected_result = 2 * (1 + 0.05) / (1 - abs(stoploss))
assert isclose(result, expected_result)
assert pytest.approx(result) == expected_result
# With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 1, stoploss, 3.0)
assert isclose(result, expected_result / 3)
assert pytest.approx(result) == expected_result / 3
# max
result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 10000
@@ -426,10 +425,10 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
)
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss)
expected_result = 2 * 2 * (1 + 0.05) / (1 - abs(stoploss))
assert isclose(result, expected_result)
assert pytest.approx(result) == expected_result
# With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 5.0)
assert isclose(result, expected_result / 5)
assert pytest.approx(result) == expected_result / 5
# max
result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 20000
@@ -445,10 +444,10 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
)
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss)
expected_result = max(2, 2 * 2) * (1 + 0.05) / (1 - abs(stoploss))
assert isclose(result, expected_result)
assert pytest.approx(result) == expected_result
# With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 10)
assert isclose(result, expected_result / 10)
assert pytest.approx(result) == expected_result / 10
# min amount and cost are set (amount is minial)
markets["ETH/BTC"]["limits"] = {
@@ -461,20 +460,20 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
)
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss)
expected_result = max(8, 2 * 2) * (1 + 0.05) / (1 - abs(stoploss))
assert isclose(result, expected_result)
assert pytest.approx(result) == expected_result
# With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 7.0)
assert isclose(result, expected_result / 7.0)
assert pytest.approx(result) == expected_result / 7.0
# Max
result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 1000
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -0.4)
expected_result = max(8, 2 * 2) * 1.5
assert isclose(result, expected_result)
assert pytest.approx(result) == expected_result
# With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -0.4, 8.0)
assert isclose(result, expected_result / 8.0)
assert pytest.approx(result) == expected_result / 8.0
# Max
result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 1000
@@ -482,10 +481,10 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
# Really big stoploss
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1)
expected_result = max(8, 2 * 2) * 1.5
assert isclose(result, expected_result)
assert pytest.approx(result) == expected_result
# With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1, 12.0)
assert isclose(result, expected_result / 12)
assert pytest.approx(result) == expected_result / 12
# Max
result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 1000
@@ -501,7 +500,7 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
# Contract size 0.01
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1)
assert isclose(result, expected_result * 0.01)
assert pytest.approx(result) == expected_result * 0.01
# Max
result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 10
@@ -513,7 +512,7 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
)
# With Leverage, Contract size 10
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1, 12.0)
assert isclose(result, (expected_result / 12) * 10.0)
assert pytest.approx(result) == (expected_result / 12) * 10.0
# Max
result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 10000
@@ -3239,7 +3238,7 @@ def test_get_trades_for_order(default_conf, mocker, exchange_name, trading_mode,
orders = exchange.get_trades_for_order(order_id, 'ETH/USDT:USDT', since)
assert len(orders) == 1
assert orders[0]['price'] == 165
assert isclose(orders[0]['amount'], amount)
assert pytest.approx(orders[0]['amount']) == amount
assert api_mock.fetch_my_trades.call_count == 1
# since argument should be
assert isinstance(api_mock.fetch_my_trades.call_args[0][1], int)
@@ -3776,8 +3775,8 @@ def test__get_funding_fees_from_exchange(default_conf, mocker, exchange_name):
since=unix_time
)
assert (isclose(expected_fees, fees_from_datetime))
assert (isclose(expected_fees, fees_from_unix_time))
assert pytest.approx(expected_fees) == fees_from_datetime
assert pytest.approx(expected_fees) == fees_from_unix_time
ccxt_exceptionhandlers(
mocker,
@@ -4514,7 +4513,7 @@ def test_liquidation_price(
default_conf['liquidation_buffer'] = 0.0
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
exchange.get_maintenance_ratio_and_amt = MagicMock(return_value=(mm_ratio, maintenance_amt))
assert isclose(round(exchange.get_liquidation_price(
assert pytest.approx(round(exchange.get_liquidation_price(
pair='DOGE/USDT',
open_rate=open_rate,
is_short=is_short,
@@ -4523,7 +4522,7 @@ def test_liquidation_price(
upnl_ex_1=upnl_ex_1,
amount=amount,
stake_amount=open_rate * amount,
), 2), expected)
), 2)) == expected
def test_get_max_pair_stake_amount(
@@ -4868,8 +4867,8 @@ def test_get_max_leverage_futures(default_conf, mocker, leverage_tiers):
assert exchange.get_max_leverage("BNB/BUSD", 1.0) == 20.0
assert exchange.get_max_leverage("BNB/USDT", 100.0) == 75.0
assert exchange.get_max_leverage("BTC/USDT", 170.30) == 125.0
assert isclose(exchange.get_max_leverage("BNB/BUSD", 99999.9), 5.000005)
assert isclose(exchange.get_max_leverage("BNB/USDT", 1500), 33.333333333333333)
assert pytest.approx(exchange.get_max_leverage("BNB/BUSD", 99999.9)) == 5.000005
assert pytest.approx(exchange.get_max_leverage("BNB/USDT", 1500)) == 33.333333333333333
assert exchange.get_max_leverage("BTC/USDT", 300000000) == 2.0
assert exchange.get_max_leverage("BTC/USDT", 600000000) == 1.0 # Last tier
@@ -4986,6 +4985,7 @@ def test_get_liquidation_price1(mocker, default_conf):
is_short=False,
amount=0.8,
stake_amount=18.884 * 0.8,
wallet_balance=18.884 * 0.8,
)
assert liq_price == 17.47
@@ -4997,6 +4997,7 @@ def test_get_liquidation_price1(mocker, default_conf):
is_short=False,
amount=0.8,
stake_amount=18.884 * 0.8,
wallet_balance=18.884 * 0.8,
)
assert liq_price == 17.540699999999998
@@ -5008,6 +5009,7 @@ def test_get_liquidation_price1(mocker, default_conf):
is_short=False,
amount=0.8,
stake_amount=18.884 * 0.8,
wallet_balance=18.884 * 0.8,
)
assert liq_price is None
default_conf['trading_mode'] = 'margin'
@@ -5020,6 +5022,7 @@ def test_get_liquidation_price1(mocker, default_conf):
is_short=False,
amount=0.8,
stake_amount=18.884 * 0.8,
wallet_balance=18.884 * 0.8,
)
@@ -5145,7 +5148,7 @@ def test_get_liquidation_price(
else:
buffer_amount = liquidation_buffer * abs(open_rate - expected_liq)
expected_liq = expected_liq - buffer_amount if is_short else expected_liq + buffer_amount
assert isclose(expected_liq, liq)
assert pytest.approx(expected_liq) == liq
@pytest.mark.parametrize('contract_size,order_amount', [

View File

@@ -45,7 +45,6 @@ def freqai_conf(default_conf, tmpdir):
"principal_component_analysis": False,
"use_SVM_to_remove_outliers": True,
"stratify_training_data": 0,
"indicator_max_period_candles": 10,
"indicator_periods_candles": [10],
},
"data_split_parameters": {"test_size": 0.33, "random_state": 1},

View File

@@ -48,10 +48,4 @@ def test_freqai_backtest_load_data(freqai_conf, mocker, caplog):
assert log_has_re('Increasing startup_candle_count for freqai to.*', caplog)
del freqai_conf['freqai']['startup_candles']
backtesting = Backtesting(freqai_conf)
with pytest.raises(OperationalException,
match=r'FreqAI backtesting module.*startup_candles in config.'):
backtesting.load_bt_data()
Backtesting.cleanup()

View File

@@ -1,5 +1,5 @@
import datetime
import shutil
from datetime import datetime, timedelta, timezone
from pathlib import Path
import pytest
@@ -57,16 +57,13 @@ def test_split_timerange(
shutil.rmtree(Path(dk.full_path))
@pytest.mark.parametrize(
"timestamp, expected",
[
(datetime.datetime.now(tz=datetime.timezone.utc).timestamp() - 7200, True),
(datetime.datetime.now(tz=datetime.timezone.utc).timestamp(), False),
],
)
def test_check_if_model_expired(mocker, freqai_conf, timestamp, expected):
def test_check_if_model_expired(mocker, freqai_conf):
dk = get_patched_data_kitchen(mocker, freqai_conf)
assert dk.check_if_model_expired(timestamp) == expected
now = datetime.now(tz=timezone.utc).timestamp()
assert dk.check_if_model_expired(now) is False
now = (datetime.now(tz=timezone.utc) - timedelta(hours=2)).timestamp()
assert dk.check_if_model_expired(now) is True
shutil.rmtree(Path(dk.full_path))
@@ -75,7 +72,7 @@ def test_use_DBSCAN_to_remove_outliers(mocker, freqai_conf, caplog):
# freqai_conf['freqai']['feature_parameters'].update({"outlier_protection_percentage": 1})
freqai.dk.use_DBSCAN_to_remove_outliers(predict=False)
assert log_has_re(
"DBSCAN found eps of 2.42.",
"DBSCAN found eps of 2.36.",
caplog,
)
@@ -84,7 +81,7 @@ def test_compute_distances(mocker, freqai_conf):
freqai = make_data_dictionary(mocker, freqai_conf)
freqai_conf['freqai']['feature_parameters'].update({"DI_threshold": 1})
avg_mean_dist = freqai.dk.compute_distances()
assert round(avg_mean_dist, 2) == 2.56
assert round(avg_mean_dist, 2) == 2.54
def test_use_SVM_to_remove_outliers_and_outlier_protection(mocker, freqai_conf, caplog):
@@ -92,7 +89,7 @@ def test_use_SVM_to_remove_outliers_and_outlier_protection(mocker, freqai_conf,
freqai_conf['freqai']['feature_parameters'].update({"outlier_protection_percentage": 0.1})
freqai.dk.use_SVM_to_remove_outliers(predict=False)
assert log_has_re(
"SVM detected 8.46%",
"SVM detected 8.09%",
caplog,
)

View File

@@ -176,6 +176,7 @@ def test_extract_data_and_train_model_LightGBMClassifier(mocker, freqai_conf):
def test_start_backtesting(mocker, freqai_conf):
freqai_conf.update({"timerange": "20180120-20180130"})
freqai_conf.get("freqai", {}).update({"save_backtest_models": True})
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
exchange = get_patched_exchange(mocker, freqai_conf)
strategy.dp = DataProvider(freqai_conf, exchange)
@@ -194,7 +195,7 @@ def test_start_backtesting(mocker, freqai_conf):
freqai.start_backtesting(df, metadata, freqai.dk)
model_folders = [x for x in freqai.dd.full_path.iterdir() if x.is_dir()]
assert len(model_folders) == 5
assert len(model_folders) == 6
shutil.rmtree(Path(freqai.dk.full_path))
@@ -202,6 +203,7 @@ def test_start_backtesting(mocker, freqai_conf):
def test_start_backtesting_subdaily_backtest_period(mocker, freqai_conf):
freqai_conf.update({"timerange": "20180120-20180124"})
freqai_conf.get("freqai", {}).update({"backtest_period_days": 0.5})
freqai_conf.get("freqai", {}).update({"save_backtest_models": True})
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
exchange = get_patched_exchange(mocker, freqai_conf)
strategy.dp = DataProvider(freqai_conf, exchange)
@@ -219,13 +221,14 @@ def test_start_backtesting_subdaily_backtest_period(mocker, freqai_conf):
metadata = {"pair": "LTC/BTC"}
freqai.start_backtesting(df, metadata, freqai.dk)
model_folders = [x for x in freqai.dd.full_path.iterdir() if x.is_dir()]
assert len(model_folders) == 8
assert len(model_folders) == 9
shutil.rmtree(Path(freqai.dk.full_path))
def test_start_backtesting_from_existing_folder(mocker, freqai_conf, caplog):
freqai_conf.update({"timerange": "20180120-20180130"})
freqai_conf.get("freqai", {}).update({"save_backtest_models": True})
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
exchange = get_patched_exchange(mocker, freqai_conf)
strategy.dp = DataProvider(freqai_conf, exchange)
@@ -244,7 +247,7 @@ def test_start_backtesting_from_existing_folder(mocker, freqai_conf, caplog):
freqai.start_backtesting(df, metadata, freqai.dk)
model_folders = [x for x in freqai.dd.full_path.iterdir() if x.is_dir()]
assert len(model_folders) == 5
assert len(model_folders) == 6
# without deleting the exiting folder structure, re-run
@@ -265,10 +268,14 @@ def test_start_backtesting_from_existing_folder(mocker, freqai_conf, caplog):
freqai.start_backtesting(df, metadata, freqai.dk)
assert log_has_re(
"Found model at ",
"Found backtesting prediction file ",
caplog,
)
path = (freqai.dd.full_path / freqai.dk.backtest_predictions_folder)
prediction_files = [x for x in path.iterdir() if x.is_file()]
assert len(prediction_files) == 5
shutil.rmtree(Path(freqai.dk.full_path))

View File

@@ -1,5 +1,3 @@
from math import isclose
import pytest
from freqtrade.leverage import interest
@@ -30,9 +28,9 @@ twentyfive_hours = FtPrecise(25.0)
def test_interest(exchange, interest_rate, hours, expected):
borrowed = FtPrecise(60.0)
assert isclose(interest(
assert pytest.approx(float(interest(
exchange_name=exchange,
borrowed=borrowed,
rate=FtPrecise(interest_rate),
hours=hours
), expected)
))) == expected

View File

@@ -37,6 +37,7 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool,
trade.orders.append(Order(
ft_order_side=trade.entry_side,
order_id=f'{pair}-{trade.entry_side}-{trade.open_date}',
ft_is_open=False,
ft_pair=pair,
amount=trade.amount,
filled=trade.amount,
@@ -51,6 +52,7 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool,
trade.orders.append(Order(
ft_order_side=trade.exit_side,
order_id=f'{pair}-{trade.exit_side}-{trade.close_date}',
ft_is_open=False,
ft_pair=pair,
amount=trade.amount,
filled=trade.amount,

View File

@@ -2138,11 +2138,11 @@ def test_send_msg_strategy_msg_notification(default_conf, mocker) -> None:
def test_send_msg_unknown_type(default_conf, mocker) -> None:
telegram, _, _ = get_telegram_testobject(mocker, default_conf)
with pytest.raises(NotImplementedError, match=r'Unknown message type: None'):
telegram.send_msg({
'type': None,
})
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
telegram.send_msg({
'type': None,
})
msg_mock.call_count == 0
@pytest.mark.parametrize('message_type,enter,enter_signal,leverage', [

View File

@@ -1,5 +1,3 @@
from math import isclose
import numpy as np
import pandas as pd
import pytest
@@ -165,7 +163,7 @@ def test_stoploss_from_open():
or (side == 'short' and expected_stop_price < current_price)):
assert stoploss == 0
else:
assert isclose(stop_price, expected_stop_price, rel_tol=0.00001)
assert pytest.approx(stop_price) == expected_stop_price
def test_stoploss_from_absolute():

View File

@@ -1051,8 +1051,6 @@ def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_order, is_sho
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
return_value=order['amount'])
stoploss = MagicMock(return_value={'id': 13434334})
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss)
@@ -1875,8 +1873,6 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog
mocker.patch('freqtrade.exchange.Exchange.fetch_order',
return_value=limit_order[entry_side(is_short)])
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
return_value=limit_order[entry_side(is_short)]['amount'])
trade = MagicMock()
trade.is_short = is_short
@@ -1886,14 +1882,13 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog
n = freqtrade.exit_positions(trades)
assert n == 0
# Test amount not modified by fee-logic
assert not log_has(
'Applying fee to amount for Trade {} from 30.0 to 90.81'.format(trade), caplog
)
assert not log_has_re(r'Applying fee to amount for Trade .*', caplog)
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=90.81)
gra = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=0.0)
# test amount modified by fee-logic
n = freqtrade.exit_positions(trades)
assert n == 0
assert gra.call_count == 0
@pytest.mark.parametrize("is_short", [False, True])
@@ -1927,8 +1922,7 @@ def test_update_trade_state(mocker, default_conf_usdt, limit_order, is_short, ca
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
return_value=order['amount'])
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=0.0)
order_id = order['id']
trade = Trade(
@@ -1960,11 +1954,11 @@ def test_update_trade_state(mocker, default_conf_usdt, limit_order, is_short, ca
assert trade.amount == order['amount']
trade.open_order_id = order_id
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=90.81)
assert trade.amount != 90.81
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=0.01)
assert trade.amount == 30.0
# test amount modified by fee-logic
freqtrade.update_trade_state(trade, order_id)
assert trade.amount == 90.81
assert trade.amount == 29.99
assert trade.open_order_id is None
trade.is_open = True
@@ -4268,10 +4262,10 @@ def test_get_real_amount_quote(default_conf_usdt, trades_for_order, buy_order_fe
caplog.clear()
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
# Amount is reduced by "fee"
assert freqtrade.get_real_amount(trade, buy_order_fee, order_obj) == amount - (amount * 0.001)
assert freqtrade.get_real_amount(trade, buy_order_fee, order_obj) == (amount * 0.001)
assert log_has(
'Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, is_short=False,'
' leverage=1.0, open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992).',
' leverage=1.0, open_rate=0.24544100, open_since=closed), fee=0.008.',
caplog
)
@@ -4296,7 +4290,7 @@ def test_get_real_amount_quote_dust(default_conf_usdt, trades_for_order, buy_ord
walletmock.reset_mock()
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
# Amount is kept as is
assert freqtrade.get_real_amount(trade, buy_order_fee, order_obj) == amount
assert freqtrade.get_real_amount(trade, buy_order_fee, order_obj) is None
assert walletmock.call_count == 1
assert log_has_re(r'Fee amount for Trade.* was in base currency '
'- Eating Fee 0.008 into dust', caplog)
@@ -4319,7 +4313,7 @@ def test_get_real_amount_no_trade(default_conf_usdt, buy_order_fee, caplog, mock
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
# Amount is reduced by "fee"
assert freqtrade.get_real_amount(trade, buy_order_fee, order_obj) == amount
assert freqtrade.get_real_amount(trade, buy_order_fee, order_obj) is None
assert log_has(
'Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
'is_short=False, leverage=1.0, open_rate=0.24544100, open_since=closed) failed: '
@@ -4343,8 +4337,7 @@ def test_get_real_amount_no_trade(default_conf_usdt, buy_order_fee, caplog, mock
# from order
({'cost': 0.004, 'currency': 'LTC'}, 0.004, False, (
'Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
'is_short=False, leverage=1.0, open_rate=0.24544100, open_since=closed) (from'
' 8.0 to 7.996).'
'is_short=False, leverage=1.0, open_rate=0.24544100, open_since=closed), fee=0.004.'
)),
# invalid, no currency in from fee dict
({'cost': 0.008, 'currency': None}, 0, True, None),
@@ -4376,7 +4369,11 @@ def test_get_real_amount(
caplog.clear()
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
assert freqtrade.get_real_amount(trade, buy_order, order_obj) == amount - fee_reduction_amount
res = freqtrade.get_real_amount(trade, buy_order, order_obj)
if fee_reduction_amount == 0:
assert res is None
else:
assert res == fee_reduction_amount
if expected_log:
assert log_has(expected_log, caplog)
@@ -4422,14 +4419,14 @@ def test_get_real_amount_multi(
return_value={'ask': 0.19, 'last': 0.2})
# Amount is reduced by "fee"
expected_amount = amount - (amount * fee_reduction_amount)
expected_amount = amount * fee_reduction_amount
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
assert freqtrade.get_real_amount(trade, buy_order_fee, order_obj) == expected_amount
assert log_has(
(
'Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
'is_short=False, leverage=1.0, open_rate=0.24544100, open_since=closed) '
f'(from 8.0 to {expected_log_amount}).'
'is_short=False, leverage=1.0, open_rate=0.24544100, open_since=closed), '
f'fee={expected_amount}.'
),
caplog
)
@@ -4462,7 +4459,7 @@ def test_get_real_amount_invalid_order(default_conf_usdt, trades_for_order, buy_
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
# Amount does not change
assert freqtrade.get_real_amount(trade, limit_buy_order_usdt, order_obj) == amount
assert freqtrade.get_real_amount(trade, limit_buy_order_usdt, order_obj) is None
def test_get_real_amount_fees_order(default_conf_usdt, market_buy_order_usdt_doublefee,
@@ -4485,7 +4482,7 @@ def test_get_real_amount_fees_order(default_conf_usdt, market_buy_order_usdt_dou
# Amount does not change
assert trade.fee_open == 0.0025
order_obj = Order.parse_from_ccxt_object(market_buy_order_usdt_doublefee, 'LTC/ETH', 'buy')
assert freqtrade.get_real_amount(trade, market_buy_order_usdt_doublefee, order_obj) == 30.0
assert freqtrade.get_real_amount(trade, market_buy_order_usdt_doublefee, order_obj) is None
assert tfo_mock.call_count == 0
# Fetch fees from trades dict if available to get "proper" values
assert round(trade.fee_open, 4) == 0.001
@@ -4537,7 +4534,7 @@ def test_get_real_amount_wrong_amount_rounding(default_conf_usdt, trades_for_ord
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
# Amount changes by fee amount.
assert pytest.approx(freqtrade.get_real_amount(
trade, limit_buy_order_usdt, order_obj)) == amount - (amount * 0.001)
trade, limit_buy_order_usdt, order_obj)) == (amount * 0.001)
def test_get_real_amount_open_trade_usdt(default_conf_usdt, fee, mocker):
@@ -4559,7 +4556,7 @@ def test_get_real_amount_open_trade_usdt(default_conf_usdt, fee, mocker):
}
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
order_obj = Order.parse_from_ccxt_object(order, 'LTC/ETH', 'buy')
assert freqtrade.get_real_amount(trade, order, order_obj) == amount
assert freqtrade.get_real_amount(trade, order, order_obj) is None
def test_get_real_amount_in_point(default_conf_usdt, buy_order_fee, fee, mocker, caplog):
@@ -4616,7 +4613,7 @@ def test_get_real_amount_in_point(default_conf_usdt, buy_order_fee, fee, mocker,
order_obj = Order.parse_from_ccxt_object(buy_order_fee, 'LTC/ETH', 'buy')
res = freqtrade.get_real_amount(trade, limit_buy_order_usdt, order_obj)
assert res == amount
assert res is None
assert trade.fee_open_currency is None
assert trade.fee_open_cost is None
message = "Not updating buy-fee - rate: None, POINT."
@@ -4624,7 +4621,7 @@ def test_get_real_amount_in_point(default_conf_usdt, buy_order_fee, fee, mocker,
caplog.clear()
freqtrade.config['exchange']['unknown_fee_rate'] = 1
res = freqtrade.get_real_amount(trade, limit_buy_order_usdt, order_obj)
assert res == amount
assert res is None
assert trade.fee_open_currency == 'POINT'
assert pytest.approx(trade.fee_open_cost) == 0.3046651026
assert trade.fee_open == 0.002
@@ -4633,12 +4630,12 @@ def test_get_real_amount_in_point(default_conf_usdt, buy_order_fee, fee, mocker,
@pytest.mark.parametrize('amount,fee_abs,wallet,amount_exp', [
(8.0, 0.0, 10, 8),
(8.0, 0.0, 0, 8),
(8.0, 0.1, 0, 7.9),
(8.0, 0.1, 10, 8),
(8.0, 0.1, 8.0, 8.0),
(8.0, 0.1, 7.9, 7.9),
(8.0, 0.0, 10, None),
(8.0, 0.0, 0, None),
(8.0, 0.1, 0, 0.1),
(8.0, 0.1, 10, None),
(8.0, 0.1, 8.0, None),
(8.0, 0.1, 7.9, 0.1),
])
def test_apply_fee_conditional(default_conf_usdt, fee, mocker,
amount, fee_abs, wallet, amount_exp):
@@ -4653,11 +4650,17 @@ def test_apply_fee_conditional(default_conf_usdt, fee, mocker,
fee_close=fee.return_value,
open_order_id="123456"
)
order = Order(
ft_order_side='buy',
order_id='100',
ft_pair=trade.pair,
ft_is_open=True,
)
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
walletmock.reset_mock()
# Amount is kept as is
assert freqtrade.apply_fee_conditional(trade, 'LTC', amount, fee_abs) == amount_exp
assert freqtrade.apply_fee_conditional(trade, 'LTC', amount, fee_abs, order) == amount_exp
assert walletmock.call_count == 1

View File

@@ -1,7 +1,6 @@
# pragma pylint: disable=missing-docstring, C0103
import logging
from datetime import datetime, timedelta, timezone
from math import isclose
from pathlib import Path
from types import FunctionType
from unittest.mock import MagicMock
@@ -582,25 +581,25 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee,
@pytest.mark.parametrize(
'exchange,is_short,lev,open_value,close_value,profit,profit_ratio,trading_mode,funding_fees', [
("binance", False, 1, 60.15, 65.835, 5.685, 0.09451371, spot, 0.0),
("binance", True, 1, 59.850, 66.1663784375, -6.3163784375, -0.1055368, margin, 0.0),
("binance", True, 1, 65.835, 60.151253125, 5.68374687, 0.08633321, margin, 0.0),
("binance", False, 3, 60.15, 65.83416667, 5.68416667, 0.28349958, margin, 0.0),
("binance", True, 3, 59.85, 66.1663784375, -6.3163784375, -0.31661044, margin, 0.0),
("binance", True, 3, 65.835, 60.151253125, 5.68374687, 0.25899963, margin, 0.0),
("kraken", False, 1, 60.15, 65.835, 5.685, 0.09451371, spot, 0.0),
("kraken", True, 1, 59.850, 66.231165, -6.381165, -0.1066192, margin, 0.0),
("kraken", True, 1, 65.835, 60.21015, 5.62485, 0.0854386, margin, 0.0),
("kraken", False, 3, 60.15, 65.795, 5.645, 0.28154613, margin, 0.0),
("kraken", True, 3, 59.850, 66.231165, -6.381165, -0.3198578, margin, 0.0),
("kraken", True, 3, 65.835, 60.21015, 5.62485, 0.25631579, margin, 0.0),
("binance", False, 1, 60.15, 65.835, 5.685, 0.09451371, futures, 0.0),
("binance", False, 1, 60.15, 66.835, 6.685, 0.11113881, futures, 1.0),
("binance", True, 1, 59.85, 66.165, -6.315, -0.10551378, futures, 0.0),
("binance", True, 1, 59.85, 67.165, -7.315, -0.12222222, futures, -1.0),
("binance", True, 1, 65.835, 60.15, 5.685, 0.08635224, futures, 0.0),
("binance", True, 1, 65.835, 61.15, 4.685, 0.07116276, futures, -1.0),
("binance", True, 3, 65.835, 59.15, 6.685, 0.3046252, futures, 1.0),
("binance", False, 3, 60.15, 64.835, 4.685, 0.23366583, futures, -1.0),
("binance", True, 3, 59.85, 65.165, -5.315, -0.26641604, futures, 1.0),
])
@pytest.mark.usefixtures("init_persistence")
def test_calc_open_close_trade_price(
limit_buy_order_usdt, limit_sell_order_usdt, fee, exchange, is_short, lev,
limit_order, fee, exchange, is_short, lev,
open_value, close_value, profit, profit_ratio, trading_mode, funding_fees
):
trade: Trade = Trade(
@@ -616,24 +615,30 @@ def test_calc_open_close_trade_price(
is_short=is_short,
leverage=lev,
trading_mode=trading_mode,
funding_fees=funding_fees
)
entry_order = limit_order[trade.entry_side]
exit_order = limit_order[trade.exit_side]
trade.open_order_id = f'something-{is_short}-{lev}-{exchange}'
oobj = Order.parse_from_ccxt_object(limit_buy_order_usdt, 'ADA/USDT', 'buy')
oobj = Order.parse_from_ccxt_object(entry_order, 'ADA/USDT', trade.entry_side)
oobj.trade = trade
oobj.update_from_ccxt_object(entry_order)
trade.update_trade(oobj)
oobj = Order.parse_from_ccxt_object(limit_sell_order_usdt, 'ADA/USDT', 'sell')
trade.funding_fees = funding_fees
oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', trade.exit_side)
oobj.trade = trade
oobj.update_from_ccxt_object(exit_order)
trade.update_trade(oobj)
trade.open_rate = 2.0
trade.close_rate = 2.2
trade.recalc_open_trade_value()
assert isclose(trade._calc_open_trade_value(trade.amount, trade.open_rate), open_value)
assert isclose(trade.calc_close_trade_value(trade.close_rate), close_value)
assert isclose(trade.calc_profit(trade.close_rate), round(profit, 8))
assert pytest.approx(trade.calc_profit_ratio(trade.close_rate)) == profit_ratio
assert trade.is_open is False
assert trade.funding_fees == funding_fees
assert pytest.approx(trade._calc_open_trade_value(trade.amount, trade.open_rate)) == open_value
assert pytest.approx(trade.calc_close_trade_value(trade.close_rate)) == close_value
assert pytest.approx(trade.close_profit_abs) == profit
assert pytest.approx(trade.close_profit) == profit_ratio
@pytest.mark.usefixtures("init_persistence")
@@ -655,6 +660,7 @@ def test_trade_close(fee):
trade.orders.append(Order(
ft_order_side=trade.entry_side,
order_id=f'{trade.pair}-{trade.entry_side}-{trade.open_date}',
ft_is_open=False,
ft_pair=trade.pair,
amount=trade.amount,
filled=trade.amount,
@@ -668,6 +674,7 @@ def test_trade_close(fee):
trade.orders.append(Order(
ft_order_side=trade.exit_side,
order_id=f'{trade.pair}-{trade.exit_side}-{trade.open_date}',
ft_is_open=False,
ft_pair=trade.pair,
amount=trade.amount,
filled=trade.amount,