Merge branch 'develop' into pr/mkavinkumar1/6545
This commit is contained in:
@@ -325,7 +325,7 @@ def create_mock_trades_with_leverage(fee, use_db: bool = True):
|
||||
Trade.query.session.flush()
|
||||
|
||||
|
||||
def create_mock_trades_usdt(fee, use_db: bool = True):
|
||||
def create_mock_trades_usdt(fee, is_short: Optional[bool] = False, use_db: bool = True):
|
||||
"""
|
||||
Create some fake trades ...
|
||||
"""
|
||||
@@ -335,26 +335,29 @@ def create_mock_trades_usdt(fee, use_db: bool = True):
|
||||
else:
|
||||
LocalTrade.add_bt_trade(trade)
|
||||
|
||||
is_short1 = is_short if is_short is not None else True
|
||||
is_short2 = is_short if is_short is not None else False
|
||||
|
||||
# Simulate dry_run entries
|
||||
trade = mock_trade_usdt_1(fee)
|
||||
trade = mock_trade_usdt_1(fee, is_short1)
|
||||
add_trade(trade)
|
||||
|
||||
trade = mock_trade_usdt_2(fee)
|
||||
trade = mock_trade_usdt_2(fee, is_short1)
|
||||
add_trade(trade)
|
||||
|
||||
trade = mock_trade_usdt_3(fee)
|
||||
trade = mock_trade_usdt_3(fee, is_short1)
|
||||
add_trade(trade)
|
||||
|
||||
trade = mock_trade_usdt_4(fee)
|
||||
trade = mock_trade_usdt_4(fee, is_short2)
|
||||
add_trade(trade)
|
||||
|
||||
trade = mock_trade_usdt_5(fee)
|
||||
trade = mock_trade_usdt_5(fee, is_short2)
|
||||
add_trade(trade)
|
||||
|
||||
trade = mock_trade_usdt_6(fee)
|
||||
trade = mock_trade_usdt_6(fee, is_short1)
|
||||
add_trade(trade)
|
||||
|
||||
trade = mock_trade_usdt_7(fee)
|
||||
trade = mock_trade_usdt_7(fee, is_short1)
|
||||
add_trade(trade)
|
||||
if use_db:
|
||||
Trade.commit()
|
||||
|
||||
@@ -6,47 +6,84 @@ from freqtrade.persistence.models import Order, Trade
|
||||
MOCK_TRADE_COUNT = 6
|
||||
|
||||
|
||||
def mock_order_usdt_1():
|
||||
def entry_side(is_short: bool):
|
||||
return "sell" if is_short else "buy"
|
||||
|
||||
|
||||
def exit_side(is_short: bool):
|
||||
return "buy" if is_short else "sell"
|
||||
|
||||
|
||||
def direc(is_short: bool):
|
||||
return "short" if is_short else "long"
|
||||
|
||||
|
||||
def mock_order_usdt_1(is_short: bool):
|
||||
return {
|
||||
'id': '1234',
|
||||
'symbol': 'ADA/USDT',
|
||||
'id': f'prod_entry_1_{direc(is_short)}',
|
||||
'symbol': 'LTC/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'buy',
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 2.0,
|
||||
'amount': 10.0,
|
||||
'filled': 10.0,
|
||||
'price': 10.0,
|
||||
'amount': 2.0,
|
||||
'filled': 2.0,
|
||||
'remaining': 0.0,
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_1(fee):
|
||||
def mock_order_usdt_1_exit(is_short: bool):
|
||||
return {
|
||||
'id': f'prod_exit_1_{direc(is_short)}',
|
||||
'symbol': 'LTC/USDT',
|
||||
'status': 'closed',
|
||||
'side': exit_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 8.0,
|
||||
'amount': 2.0,
|
||||
'filled': 2.0,
|
||||
'remaining': 0.0,
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_1(fee, is_short: bool):
|
||||
"""
|
||||
Simulate prod entry with open sell order
|
||||
"""
|
||||
trade = Trade(
|
||||
pair='ADA/USDT',
|
||||
pair='LTC/USDT',
|
||||
stake_amount=20.0,
|
||||
amount=10.0,
|
||||
amount_requested=10.0,
|
||||
amount=2.0,
|
||||
amount_requested=2.0,
|
||||
open_date=datetime.now(tz=timezone.utc) - timedelta(days=2, minutes=20),
|
||||
close_date=datetime.now(tz=timezone.utc) - timedelta(days=2, minutes=5),
|
||||
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,
|
||||
is_open=False,
|
||||
open_rate=10.0,
|
||||
close_rate=8.0,
|
||||
close_profit=-0.2,
|
||||
close_profit_abs=-4.0,
|
||||
exchange='binance',
|
||||
open_order_id='dry_run_buy_12345',
|
||||
strategy='StrategyTestV2',
|
||||
strategy='SampleStrategy',
|
||||
open_order_id=f'prod_exit_1_{direc(is_short)}',
|
||||
timeframe=5,
|
||||
is_short=is_short,
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_1(), 'ADA/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_1(is_short), 'LTC/USDT', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_1_exit(is_short),
|
||||
'LTC/USDT', exit_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
|
||||
def mock_order_usdt_2():
|
||||
def mock_order_usdt_2(is_short: bool):
|
||||
return {
|
||||
'id': '1235',
|
||||
'id': f'1235_{direc(is_short)}',
|
||||
'symbol': 'ETC/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'buy',
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 2.0,
|
||||
'amount': 100.0,
|
||||
@@ -55,12 +92,12 @@ def mock_order_usdt_2():
|
||||
}
|
||||
|
||||
|
||||
def mock_order_usdt_2_sell():
|
||||
def mock_order_usdt_2_exit(is_short: bool):
|
||||
return {
|
||||
'id': '12366',
|
||||
'id': f'12366_{direc(is_short)}',
|
||||
'symbol': 'ETC/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'sell',
|
||||
'side': exit_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 2.05,
|
||||
'amount': 100.0,
|
||||
@@ -69,7 +106,7 @@ def mock_order_usdt_2_sell():
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_2(fee):
|
||||
def mock_trade_usdt_2(fee, is_short: bool):
|
||||
"""
|
||||
Closed trade...
|
||||
"""
|
||||
@@ -82,30 +119,33 @@ def mock_trade_usdt_2(fee):
|
||||
fee_close=fee.return_value,
|
||||
open_rate=2.0,
|
||||
close_rate=2.05,
|
||||
close_profit=5.0,
|
||||
close_profit=0.05,
|
||||
close_profit_abs=3.9875,
|
||||
exchange='binance',
|
||||
is_open=False,
|
||||
open_order_id='dry_run_sell_12345',
|
||||
open_order_id=f'12366_{direc(is_short)}',
|
||||
strategy='StrategyTestV2',
|
||||
timeframe=5,
|
||||
exit_reason='sell_signal',
|
||||
enter_tag='TEST1',
|
||||
exit_reason='exit_signal',
|
||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
|
||||
close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
|
||||
is_short=is_short,
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_2(), 'ETC/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_2(is_short), 'ETC/USDT', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_2_sell(), 'ETC/USDT', 'sell')
|
||||
o = Order.parse_from_ccxt_object(
|
||||
mock_order_usdt_2_exit(is_short), 'ETC/USDT', exit_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
|
||||
def mock_order_usdt_3():
|
||||
def mock_order_usdt_3(is_short: bool):
|
||||
return {
|
||||
'id': '41231a12a',
|
||||
'id': f'41231a12a_{direc(is_short)}',
|
||||
'symbol': 'XRP/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'buy',
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 1.0,
|
||||
'amount': 30.0,
|
||||
@@ -114,12 +154,12 @@ def mock_order_usdt_3():
|
||||
}
|
||||
|
||||
|
||||
def mock_order_usdt_3_sell():
|
||||
def mock_order_usdt_3_exit(is_short: bool):
|
||||
return {
|
||||
'id': '41231a666a',
|
||||
'id': f'41231a666a_{direc(is_short)}',
|
||||
'symbol': 'XRP/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'sell',
|
||||
'side': exit_side(is_short),
|
||||
'type': 'stop_loss_limit',
|
||||
'price': 1.1,
|
||||
'average': 1.1,
|
||||
@@ -129,7 +169,7 @@ def mock_order_usdt_3_sell():
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_3(fee):
|
||||
def mock_trade_usdt_3(fee, is_short: bool):
|
||||
"""
|
||||
Closed trade
|
||||
"""
|
||||
@@ -142,29 +182,32 @@ def mock_trade_usdt_3(fee):
|
||||
fee_close=fee.return_value,
|
||||
open_rate=1.0,
|
||||
close_rate=1.1,
|
||||
close_profit=10.0,
|
||||
close_profit=0.1,
|
||||
close_profit_abs=9.8425,
|
||||
exchange='binance',
|
||||
is_open=False,
|
||||
strategy='StrategyTestV2',
|
||||
timeframe=5,
|
||||
enter_tag='TEST3',
|
||||
exit_reason='roi',
|
||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
|
||||
close_date=datetime.now(tz=timezone.utc),
|
||||
is_short=is_short,
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_3(), 'XRP/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_3(is_short), 'XRP/USDT', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_3_sell(), 'XRP/USDT', 'sell')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_3_exit(is_short),
|
||||
'XRP/USDT', exit_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
|
||||
def mock_order_usdt_4():
|
||||
def mock_order_usdt_4(is_short: bool):
|
||||
return {
|
||||
'id': 'prod_buy_12345',
|
||||
'id': f'prod_buy_12345_{direc(is_short)}',
|
||||
'symbol': 'ETC/USDT',
|
||||
'status': 'open',
|
||||
'side': 'buy',
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 2.0,
|
||||
'amount': 10.0,
|
||||
@@ -173,7 +216,7 @@ def mock_order_usdt_4():
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_4(fee):
|
||||
def mock_trade_usdt_4(fee, is_short: bool):
|
||||
"""
|
||||
Simulate prod entry
|
||||
"""
|
||||
@@ -188,21 +231,22 @@ def mock_trade_usdt_4(fee):
|
||||
is_open=True,
|
||||
open_rate=2.0,
|
||||
exchange='binance',
|
||||
open_order_id='prod_buy_12345',
|
||||
open_order_id=f'prod_buy_12345_{direc(is_short)}',
|
||||
strategy='StrategyTestV2',
|
||||
timeframe=5,
|
||||
is_short=is_short,
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_4(), 'ETC/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_4(is_short), 'ETC/USDT', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
|
||||
def mock_order_usdt_5():
|
||||
def mock_order_usdt_5(is_short: bool):
|
||||
return {
|
||||
'id': 'prod_buy_3455',
|
||||
'id': f'prod_buy_3455_{direc(is_short)}',
|
||||
'symbol': 'XRP/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'buy',
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 2.0,
|
||||
'amount': 10.0,
|
||||
@@ -211,12 +255,12 @@ def mock_order_usdt_5():
|
||||
}
|
||||
|
||||
|
||||
def mock_order_usdt_5_stoploss():
|
||||
def mock_order_usdt_5_stoploss(is_short: bool):
|
||||
return {
|
||||
'id': 'prod_stoploss_3455',
|
||||
'id': f'prod_stoploss_3455_{direc(is_short)}',
|
||||
'symbol': 'XRP/USDT',
|
||||
'status': 'open',
|
||||
'side': 'sell',
|
||||
'side': exit_side(is_short),
|
||||
'type': 'stop_loss_limit',
|
||||
'price': 2.0,
|
||||
'amount': 10.0,
|
||||
@@ -225,7 +269,7 @@ def mock_order_usdt_5_stoploss():
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_5(fee):
|
||||
def mock_trade_usdt_5(fee, is_short: bool):
|
||||
"""
|
||||
Simulate prod entry with stoploss
|
||||
"""
|
||||
@@ -241,22 +285,23 @@ def mock_trade_usdt_5(fee):
|
||||
open_rate=2.0,
|
||||
exchange='binance',
|
||||
strategy='SampleStrategy',
|
||||
stoploss_order_id='prod_stoploss_3455',
|
||||
stoploss_order_id=f'prod_stoploss_3455_{direc(is_short)}',
|
||||
timeframe=5,
|
||||
is_short=is_short,
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_5(), 'XRP/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_5(is_short), 'XRP/USDT', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_5_stoploss(), 'XRP/USDT', 'stoploss')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_5_stoploss(is_short), 'XRP/USDT', 'stoploss')
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
|
||||
def mock_order_usdt_6():
|
||||
def mock_order_usdt_6(is_short: bool):
|
||||
return {
|
||||
'id': 'prod_buy_6',
|
||||
'id': f'prod_entry_6_{direc(is_short)}',
|
||||
'symbol': 'LTC/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'buy',
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 10.0,
|
||||
'amount': 2.0,
|
||||
@@ -265,12 +310,12 @@ def mock_order_usdt_6():
|
||||
}
|
||||
|
||||
|
||||
def mock_order_usdt_6_sell():
|
||||
def mock_order_usdt_6_exit(is_short: bool):
|
||||
return {
|
||||
'id': 'prod_sell_6',
|
||||
'id': f'prod_exit_6_{direc(is_short)}',
|
||||
'symbol': 'LTC/USDT',
|
||||
'status': 'open',
|
||||
'side': 'sell',
|
||||
'side': exit_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 12.0,
|
||||
'amount': 2.0,
|
||||
@@ -279,7 +324,7 @@ def mock_order_usdt_6_sell():
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_6(fee):
|
||||
def mock_trade_usdt_6(fee, is_short: bool):
|
||||
"""
|
||||
Simulate prod entry with open sell order
|
||||
"""
|
||||
@@ -295,69 +340,49 @@ def mock_trade_usdt_6(fee):
|
||||
open_rate=10.0,
|
||||
exchange='binance',
|
||||
strategy='SampleStrategy',
|
||||
open_order_id="prod_sell_6",
|
||||
open_order_id=f'prod_exit_6_{direc(is_short)}',
|
||||
timeframe=5,
|
||||
is_short=is_short,
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_6(), 'LTC/USDT', 'buy')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_6(is_short), 'LTC/USDT', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_6_sell(), 'LTC/USDT', 'sell')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_6_exit(is_short),
|
||||
'LTC/USDT', exit_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
|
||||
def mock_order_usdt_7():
|
||||
def mock_order_usdt_7(is_short: bool):
|
||||
return {
|
||||
'id': 'prod_buy_7',
|
||||
'symbol': 'LTC/USDT',
|
||||
'id': f'1234_{direc(is_short)}',
|
||||
'symbol': 'ADA/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'buy',
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 10.0,
|
||||
'amount': 2.0,
|
||||
'filled': 2.0,
|
||||
'price': 2.0,
|
||||
'amount': 10.0,
|
||||
'filled': 10.0,
|
||||
'remaining': 0.0,
|
||||
}
|
||||
|
||||
|
||||
def mock_order_usdt_7_sell():
|
||||
return {
|
||||
'id': 'prod_sell_7',
|
||||
'symbol': 'LTC/USDT',
|
||||
'status': 'closed',
|
||||
'side': 'sell',
|
||||
'type': 'limit',
|
||||
'price': 8.0,
|
||||
'amount': 2.0,
|
||||
'filled': 2.0,
|
||||
'remaining': 0.0,
|
||||
}
|
||||
|
||||
|
||||
def mock_trade_usdt_7(fee):
|
||||
"""
|
||||
Simulate prod entry with open sell order
|
||||
"""
|
||||
def mock_trade_usdt_7(fee, is_short: bool):
|
||||
trade = Trade(
|
||||
pair='LTC/USDT',
|
||||
pair='ADA/USDT',
|
||||
stake_amount=20.0,
|
||||
amount=2.0,
|
||||
amount_requested=2.0,
|
||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
|
||||
close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||
amount=10.0,
|
||||
amount_requested=10.0,
|
||||
fee_open=fee.return_value,
|
||||
fee_close=fee.return_value,
|
||||
is_open=False,
|
||||
open_rate=10.0,
|
||||
close_rate=8.0,
|
||||
close_profit=-0.2,
|
||||
close_profit_abs=-4.0,
|
||||
is_open=True,
|
||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=17),
|
||||
open_rate=2.0,
|
||||
exchange='binance',
|
||||
strategy='SampleStrategy',
|
||||
open_order_id="prod_sell_6",
|
||||
open_order_id=f'1234_{direc(is_short)}',
|
||||
strategy='StrategyTestV2',
|
||||
timeframe=5,
|
||||
is_short=is_short,
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_7(), 'LTC/USDT', 'buy')
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_7_sell(), 'LTC/USDT', 'sell')
|
||||
o = Order.parse_from_ccxt_object(mock_order_usdt_7(is_short), 'ADA/USDT', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
@@ -85,7 +85,7 @@ def test_load_backtest_data_new_format(testdatadir):
|
||||
filename = testdatadir / "backtest_results/backtest-result_new.json"
|
||||
bt_data = load_backtest_data(filename)
|
||||
assert isinstance(bt_data, DataFrame)
|
||||
assert set(bt_data.columns) == set(BT_DATA_COLUMNS + ['close_timestamp', 'open_timestamp'])
|
||||
assert set(bt_data.columns) == set(BT_DATA_COLUMNS)
|
||||
assert len(bt_data) == 179
|
||||
|
||||
# Test loading from string (must yield same result)
|
||||
@@ -110,7 +110,7 @@ def test_load_backtest_data_multi(testdatadir):
|
||||
bt_data = load_backtest_data(filename, strategy=strategy)
|
||||
assert isinstance(bt_data, DataFrame)
|
||||
assert set(bt_data.columns) == set(
|
||||
BT_DATA_COLUMNS + ['close_timestamp', 'open_timestamp'])
|
||||
BT_DATA_COLUMNS)
|
||||
assert len(bt_data) == 179
|
||||
|
||||
# Test loading from string (must yield same result)
|
||||
|
||||
@@ -154,6 +154,7 @@ def test_stoploss_adjust_binance(mocker, default_conf, sl1, sl2, sl3, side):
|
||||
order = {
|
||||
'type': 'stop_loss_limit',
|
||||
'price': 1500,
|
||||
'stopPrice': 1500,
|
||||
'info': {'stopPrice': 1500},
|
||||
}
|
||||
assert exchange.stoploss_adjust(sl1, order, side=side)
|
||||
|
||||
@@ -795,10 +795,27 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
'is_open': [False, False],
|
||||
'enter_tag': [None, None],
|
||||
"is_short": [False, False],
|
||||
'open_timestamp': [1517251200000, 1517283000000],
|
||||
'close_timestamp': [1517265300000, 1517285400000],
|
||||
'orders': [
|
||||
[
|
||||
{'amount': 0.00957442, 'safe_price': 0.104445, 'ft_order_side': 'buy',
|
||||
'order_filled_timestamp': 1517251200000, 'ft_is_entry': True},
|
||||
{'amount': 0.00957442, 'safe_price': 0.10496853383458644, 'ft_order_side': 'sell',
|
||||
'order_filled_timestamp': 1517265300000, 'ft_is_entry': False}
|
||||
], [
|
||||
{'amount': 0.0097064, 'safe_price': 0.10302485, 'ft_order_side': 'buy',
|
||||
'order_filled_timestamp': 1517283000000, 'ft_is_entry': True},
|
||||
{'amount': 0.0097064, 'safe_price': 0.10354126528822055, 'ft_order_side': 'sell',
|
||||
'order_filled_timestamp': 1517285400000, 'ft_is_entry': False}
|
||||
]
|
||||
]
|
||||
})
|
||||
pd.testing.assert_frame_equal(results, expected)
|
||||
assert 'orders' in results.columns
|
||||
data_pair = processed[pair]
|
||||
for _, t in results.iterrows():
|
||||
assert len(t['orders']) == 2
|
||||
ln = data_pair.loc[data_pair["date"] == t["open_date"]]
|
||||
# Check open trade rate alignes to open rate
|
||||
assert ln is not None
|
||||
|
||||
@@ -72,9 +72,14 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) ->
|
||||
'is_open': [False, False],
|
||||
'enter_tag': [None, None],
|
||||
'is_short': [False, False],
|
||||
'open_timestamp': [1517251200000, 1517283000000],
|
||||
'close_timestamp': [1517265300000, 1517285400000],
|
||||
})
|
||||
pd.testing.assert_frame_equal(results, expected)
|
||||
pd.testing.assert_frame_equal(results.drop(columns=['orders']), expected)
|
||||
data_pair = processed[pair]
|
||||
assert len(results.iloc[0]['orders']) == 6
|
||||
assert len(results.iloc[1]['orders']) == 2
|
||||
|
||||
for _, t in results.iterrows():
|
||||
ln = data_pair.loc[data_pair["date"] == t["open_date"]]
|
||||
# Check open trade rate alignes to open rate
|
||||
|
||||
@@ -509,7 +509,6 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
|
||||
hyperopt.min_date = Arrow(2017, 12, 10)
|
||||
hyperopt.max_date = Arrow(2017, 12, 13)
|
||||
hyperopt.init_spaces()
|
||||
hyperopt.dimensions = hyperopt.dimensions
|
||||
generate_optimizer_value = hyperopt.generate_optimizer(list(optimizer_param.values()))
|
||||
assert generate_optimizer_value == response_expected
|
||||
|
||||
|
||||
@@ -762,8 +762,8 @@ def test_PerformanceFilter_keep_mid_order(mocker, default_conf_usdt, fee, caplog
|
||||
with time_machine.travel("2021-09-01 05:00:00 +00:00") as t:
|
||||
create_mock_trades_usdt(fee)
|
||||
pm.refresh_pairlist()
|
||||
assert pm.whitelist == ['XRP/USDT', 'ETC/USDT', 'ETH/USDT',
|
||||
'NEO/USDT', 'TKN/USDT', 'ADA/USDT', 'LTC/USDT']
|
||||
assert pm.whitelist == ['XRP/USDT', 'ETC/USDT', 'ETH/USDT', 'LTC/USDT',
|
||||
'NEO/USDT', 'TKN/USDT', 'ADA/USDT', ]
|
||||
# assert log_has_re(r'Removing pair .* since .* is below .*', caplog)
|
||||
|
||||
# Move to "outside" of lookback window, so original sorting is restored.
|
||||
|
||||
@@ -11,11 +11,11 @@ from freqtrade.edge import PairInfo
|
||||
from freqtrade.enums import SignalDirection, State, TradingMode
|
||||
from freqtrade.exceptions import ExchangeError, InvalidOrderException, TemporaryError
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.persistence.models import Order
|
||||
from freqtrade.persistence.pairlock_middleware import PairLocks
|
||||
from freqtrade.rpc import RPC, RPCException
|
||||
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
|
||||
from tests.conftest import create_mock_trades, get_patched_freqtradebot, patch_get_signal
|
||||
from tests.conftest import (create_mock_trades, create_mock_trades_usdt, get_patched_freqtradebot,
|
||||
patch_get_signal)
|
||||
|
||||
|
||||
# Functions for recurrent object patching
|
||||
@@ -286,8 +286,8 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
|
||||
assert isnan(fiat_profit_sum)
|
||||
|
||||
|
||||
def test_rpc_daily_profit(default_conf, update, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, markets, mocker) -> None:
|
||||
def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, markets, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -296,45 +296,35 @@ def test_rpc_daily_profit(default_conf, update, ticker, fee,
|
||||
markets=PropertyMock(return_value=markets)
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot)
|
||||
stake_currency = default_conf['stake_currency']
|
||||
fiat_display_currency = default_conf['fiat_display_currency']
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
stake_currency = default_conf_usdt['stake_currency']
|
||||
fiat_display_currency = default_conf_usdt['fiat_display_currency']
|
||||
|
||||
rpc = RPC(freqtradebot)
|
||||
rpc._fiat_converter = CryptoToFiatConverter()
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
|
||||
# Simulate buy & sell
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
|
||||
# Try valid data
|
||||
update.message.text = '/daily 2'
|
||||
days = rpc._rpc_daily_profit(7, stake_currency, fiat_display_currency)
|
||||
days = rpc._rpc_timeunit_profit(7, stake_currency, fiat_display_currency)
|
||||
assert len(days['data']) == 7
|
||||
assert days['stake_currency'] == default_conf['stake_currency']
|
||||
assert days['fiat_display_currency'] == default_conf['fiat_display_currency']
|
||||
assert days['stake_currency'] == default_conf_usdt['stake_currency']
|
||||
assert days['fiat_display_currency'] == default_conf_usdt['fiat_display_currency']
|
||||
for day in days['data']:
|
||||
# [datetime.date(2018, 1, 11), '0.00000000 BTC', '0.000 USD']
|
||||
assert (day['abs_profit'] == 0.0 or
|
||||
day['abs_profit'] == 0.00006217)
|
||||
|
||||
assert (day['fiat_value'] == 0.0 or
|
||||
day['fiat_value'] == 0.76748865)
|
||||
# {'date': datetime.date(2022, 6, 11), 'abs_profit': 13.8299999,
|
||||
# 'starting_balance': 1055.37, 'rel_profit': 0.0131044,
|
||||
# 'fiat_value': 0.0, 'trade_count': 2}
|
||||
assert day['abs_profit'] in (0.0, pytest.approx(13.8299999), pytest.approx(-4.0))
|
||||
assert day['rel_profit'] in (0.0, pytest.approx(0.01310441), pytest.approx(-0.00377583))
|
||||
assert day['trade_count'] in (0, 1, 2)
|
||||
assert day['starting_balance'] in (pytest.approx(1059.37), pytest.approx(1055.37))
|
||||
assert day['fiat_value'] in (0.0, )
|
||||
# ensure first day is current date
|
||||
assert str(days['data'][0]['date']) == str(datetime.utcnow().date())
|
||||
|
||||
# Try invalid data
|
||||
with pytest.raises(RPCException, match=r'.*must be an integer greater than 0*'):
|
||||
rpc._rpc_daily_profit(0, stake_currency, fiat_display_currency)
|
||||
rpc._rpc_timeunit_profit(0, stake_currency, fiat_display_currency)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('is_short', [True, False])
|
||||
@@ -418,13 +408,8 @@ def test_rpc_delete_trade(mocker, default_conf, fee, markets, caplog, is_short):
|
||||
assert stoploss_mock.call_count == 0
|
||||
|
||||
|
||||
def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
|
||||
limit_buy_order, limit_sell_order, mocker) -> None:
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.fiat_convert.CoinGeckoAPI',
|
||||
get_price=MagicMock(return_value={'bitcoin': {'usd': 15000.0}}),
|
||||
)
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=1.1)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -432,10 +417,9 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot)
|
||||
stake_currency = default_conf['stake_currency']
|
||||
fiat_display_currency = default_conf['fiat_display_currency']
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
stake_currency = default_conf_usdt['stake_currency']
|
||||
fiat_display_currency = default_conf_usdt['fiat_display_currency']
|
||||
|
||||
rpc = RPC(freqtradebot)
|
||||
rpc._fiat_converter = CryptoToFiatConverter()
|
||||
@@ -448,75 +432,40 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
|
||||
assert res['latest_trade_timestamp'] == 0
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Update the ticker with a market going up
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_sell_up
|
||||
)
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Update the ticker with a market going up
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_sell_up
|
||||
)
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
|
||||
assert prec_satoshi(stats['profit_closed_coin'], 6.217e-05)
|
||||
assert prec_satoshi(stats['profit_closed_percent_mean'], 6.2)
|
||||
assert prec_satoshi(stats['profit_closed_fiat'], 0.93255)
|
||||
assert prec_satoshi(stats['profit_all_coin'], 5.802e-05)
|
||||
assert prec_satoshi(stats['profit_all_percent_mean'], 2.89)
|
||||
assert prec_satoshi(stats['profit_all_fiat'], 0.8703)
|
||||
assert stats['trade_count'] == 2
|
||||
assert stats['first_trade_date'] == 'just now'
|
||||
assert stats['latest_trade_date'] == 'just now'
|
||||
assert stats['avg_duration'] in ('0:00:00', '0:00:01', '0:00:02')
|
||||
assert stats['best_pair'] == 'ETH/BTC'
|
||||
assert prec_satoshi(stats['best_rate'], 6.2)
|
||||
assert pytest.approx(stats['profit_closed_coin']) == 9.83
|
||||
assert pytest.approx(stats['profit_closed_percent_mean']) == -1.67
|
||||
assert pytest.approx(stats['profit_closed_fiat']) == 10.813
|
||||
assert pytest.approx(stats['profit_all_coin']) == -77.45964918
|
||||
assert pytest.approx(stats['profit_all_percent_mean']) == -57.86
|
||||
assert pytest.approx(stats['profit_all_fiat']) == -85.205614098
|
||||
assert stats['trade_count'] == 7
|
||||
assert stats['first_trade_date'] == '2 days ago'
|
||||
assert stats['latest_trade_date'] == '17 minutes ago'
|
||||
assert stats['avg_duration'] in ('0:17:40')
|
||||
assert stats['best_pair'] == 'XRP/USDT'
|
||||
assert stats['best_rate'] == 10.0
|
||||
|
||||
# Test non-available pair
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_rate',
|
||||
MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available")))
|
||||
MagicMock(side_effect=ExchangeError("Pair 'XRP/USDT' not available")))
|
||||
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
|
||||
assert stats['trade_count'] == 2
|
||||
assert stats['first_trade_date'] == 'just now'
|
||||
assert stats['latest_trade_date'] == 'just now'
|
||||
assert stats['avg_duration'] in ('0:00:00', '0:00:01', '0:00:02')
|
||||
assert stats['best_pair'] == 'ETH/BTC'
|
||||
assert prec_satoshi(stats['best_rate'], 6.2)
|
||||
assert stats['trade_count'] == 7
|
||||
assert stats['first_trade_date'] == '2 days ago'
|
||||
assert stats['latest_trade_date'] == '17 minutes ago'
|
||||
assert stats['avg_duration'] in ('0:17:40')
|
||||
assert stats['best_pair'] == 'XRP/USDT'
|
||||
assert stats['best_rate'] == 10.0
|
||||
assert isnan(stats['profit_all_coin'])
|
||||
|
||||
|
||||
# Test that rpc_trade_statistics can handle trades that lacks
|
||||
# trade.open_rate (it is set to None)
|
||||
def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee,
|
||||
ticker_sell_up, limit_buy_order, limit_sell_order):
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.fiat_convert.CoinGeckoAPI',
|
||||
get_price=MagicMock(return_value={'bitcoin': {'usd': 15000.0}}),
|
||||
)
|
||||
def test_rpc_trade_statistics_closed(mocker, default_conf_usdt, ticker, fee):
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
|
||||
return_value=15000.0)
|
||||
return_value=1.1)
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -524,46 +473,32 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
patch_get_signal(freqtradebot)
|
||||
stake_currency = default_conf['stake_currency']
|
||||
fiat_display_currency = default_conf['fiat_display_currency']
|
||||
stake_currency = default_conf_usdt['stake_currency']
|
||||
fiat_display_currency = default_conf_usdt['fiat_display_currency']
|
||||
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
# Update the ticker with a market going up
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_sell_up,
|
||||
get_fee=fee
|
||||
)
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
for trade in Trade.query.order_by(Trade.id).all():
|
||||
trade.open_rate = None
|
||||
|
||||
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
|
||||
assert prec_satoshi(stats['profit_closed_coin'], 0)
|
||||
assert prec_satoshi(stats['profit_closed_percent_mean'], 0)
|
||||
assert prec_satoshi(stats['profit_closed_fiat'], 0)
|
||||
assert prec_satoshi(stats['profit_all_coin'], 0)
|
||||
assert prec_satoshi(stats['profit_all_percent_mean'], 0)
|
||||
assert prec_satoshi(stats['profit_all_fiat'], 0)
|
||||
assert stats['trade_count'] == 1
|
||||
assert stats['first_trade_date'] == 'just now'
|
||||
assert stats['latest_trade_date'] == 'just now'
|
||||
assert stats['profit_closed_coin'] == 0
|
||||
assert stats['profit_closed_percent_mean'] == 0
|
||||
assert stats['profit_closed_fiat'] == 0
|
||||
assert stats['profit_all_coin'] == 0
|
||||
assert stats['profit_all_percent_mean'] == 0
|
||||
assert stats['profit_all_fiat'] == 0
|
||||
assert stats['trade_count'] == 7
|
||||
assert stats['first_trade_date'] == '2 days ago'
|
||||
assert stats['latest_trade_date'] == '17 minutes ago'
|
||||
assert stats['avg_duration'] == '0:00:00'
|
||||
assert stats['best_pair'] == 'ETH/BTC'
|
||||
assert prec_satoshi(stats['best_rate'], 6.2)
|
||||
assert stats['best_pair'] == 'XRP/USDT'
|
||||
assert stats['best_rate'] == 10.0
|
||||
|
||||
|
||||
def test_rpc_balance_handle_error(default_conf, mocker):
|
||||
@@ -916,8 +851,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
|
||||
assert cancel_order_mock.call_count == 3
|
||||
|
||||
|
||||
def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, mocker) -> None:
|
||||
def test_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -926,34 +860,21 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
patch_get_signal(freqtradebot)
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
res = rpc._rpc_performance()
|
||||
assert len(res) == 1
|
||||
assert res[0]['pair'] == 'ETH/BTC'
|
||||
assert len(res) == 3
|
||||
assert res[0]['pair'] == 'XRP/USDT'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||
assert res[0]['profit_pct'] == 10.0
|
||||
|
||||
|
||||
def test_enter_tag_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, mocker) -> None:
|
||||
def test_enter_tag_performance_handle(default_conf, ticker, fee, mocker) -> None:
|
||||
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -967,34 +888,22 @@ def test_enter_tag_performance_handle(default_conf, ticker, limit_buy_order, fee
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
create_mock_trades_usdt(fee)
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
res = rpc._rpc_enter_tag_performance(None)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0]['enter_tag'] == 'Other'
|
||||
assert len(res) == 3
|
||||
assert res[0]['enter_tag'] == 'TEST3'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||
assert res[0]['profit_pct'] == 10.0
|
||||
|
||||
trade.enter_tag = "TEST_TAG"
|
||||
res = rpc._rpc_enter_tag_performance(None)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0]['enter_tag'] == 'TEST_TAG'
|
||||
assert len(res) == 3
|
||||
assert res[0]['enter_tag'] == 'TEST3'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||
assert res[0]['profit_pct'] == 10.0
|
||||
|
||||
|
||||
def test_enter_tag_performance_handle_2(mocker, default_conf, markets, fee):
|
||||
@@ -1026,8 +935,7 @@ def test_enter_tag_performance_handle_2(mocker, default_conf, markets, fee):
|
||||
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
||||
|
||||
|
||||
def test_exit_reason_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, mocker) -> None:
|
||||
def test_exit_reason_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -1036,39 +944,22 @@ def test_exit_reason_performance_handle(default_conf, ticker, limit_buy_order, f
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
patch_get_signal(freqtradebot)
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
res = rpc._rpc_exit_reason_performance(None)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0]['exit_reason'] == 'Other'
|
||||
assert len(res) == 3
|
||||
assert res[0]['exit_reason'] == 'roi'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||
assert res[0]['profit_pct'] == 10.0
|
||||
|
||||
trade.exit_reason = "TEST1"
|
||||
res = rpc._rpc_exit_reason_performance(None)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0]['exit_reason'] == 'TEST1'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||
assert res[1]['exit_reason'] == 'exit_signal'
|
||||
assert res[2]['exit_reason'] == 'Other'
|
||||
|
||||
|
||||
def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee):
|
||||
@@ -1100,8 +991,7 @@ def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee):
|
||||
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
||||
|
||||
|
||||
def test_mix_tag_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, mocker) -> None:
|
||||
def test_mix_tag_performance_handle(default_conf, ticker, fee, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -1115,35 +1005,14 @@ def test_mix_tag_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
res = rpc._rpc_mix_tag_performance(None)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0]['mix_tag'] == 'Other Other'
|
||||
assert len(res) == 3
|
||||
assert res[0]['mix_tag'] == 'TEST3 roi'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||
|
||||
trade.enter_tag = "TESTBUY"
|
||||
trade.exit_reason = "TESTSELL"
|
||||
res = rpc._rpc_mix_tag_performance(None)
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0]['mix_tag'] == 'TESTBUY TESTSELL'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||
assert res[0]['profit_pct'] == 10.0
|
||||
|
||||
|
||||
def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee):
|
||||
|
||||
@@ -27,8 +27,9 @@ from freqtrade.persistence.models import Order
|
||||
from freqtrade.rpc import RPC
|
||||
from freqtrade.rpc.rpc import RPCException
|
||||
from freqtrade.rpc.telegram import Telegram, authorized_only
|
||||
from tests.conftest import (CURRENT_TEST_STRATEGY, create_mock_trades, get_patched_freqtradebot,
|
||||
log_has, log_has_re, patch_exchange, patch_get_signal, patch_whitelist)
|
||||
from tests.conftest import (CURRENT_TEST_STRATEGY, create_mock_trades, create_mock_trades_usdt,
|
||||
get_patched_freqtradebot, log_has, log_has_re, patch_exchange,
|
||||
patch_get_signal, patch_whitelist)
|
||||
|
||||
|
||||
class DummyCls(Telegram):
|
||||
@@ -404,12 +405,10 @@ def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None:
|
||||
assert msg_mock.call_count == 1
|
||||
|
||||
|
||||
def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, mocker) -> None:
|
||||
default_conf['max_open_trades'] = 1
|
||||
def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time_machine) -> None:
|
||||
mocker.patch(
|
||||
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
|
||||
return_value=15000.0
|
||||
return_value=1.1
|
||||
)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -417,27 +416,12 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
|
||||
patch_get_signal(freqtradebot)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
|
||||
# Move date to within day
|
||||
time_machine.move_to('2022-06-11 08:00:00+00:00')
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobjs = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobjs)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Try valid data
|
||||
# /daily 2
|
||||
@@ -448,10 +432,11 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
assert "Daily Profit over the last 2 days</b>:" in msg_mock.call_args_list[0][0][0]
|
||||
assert 'Day ' in msg_mock.call_args_list[0][0][0]
|
||||
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(2) 13.83 USDT 15.21 USD 1.31%' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Reset msg_mock
|
||||
msg_mock.reset_mock()
|
||||
@@ -460,32 +445,23 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
assert msg_mock.call_count == 1
|
||||
assert "Daily Profit over the last 7 days</b>:" in msg_mock.call_args_list[0][0][0]
|
||||
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert str((datetime.utcnow() - timedelta(days=5)).date()) in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(1)' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Reset msg_mock
|
||||
msg_mock.reset_mock()
|
||||
freqtradebot.config['max_open_trades'] = 2
|
||||
# Add two other trades
|
||||
n = freqtradebot.enter_positions()
|
||||
assert n == 2
|
||||
|
||||
trades = Trade.query.all()
|
||||
for trade in trades:
|
||||
trade.update_trade(oobj)
|
||||
trade.update_trade(oobjs)
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
|
||||
# /daily 1
|
||||
context = MagicMock()
|
||||
context.args = ["1"]
|
||||
telegram._daily(update=update, context=context)
|
||||
assert str(' 0.00018651 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 2.798 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 3 trades') in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
@@ -514,15 +490,14 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
context = MagicMock()
|
||||
context.args = ["today"]
|
||||
telegram._daily(update=update, context=context)
|
||||
assert str('Daily Profit over the last 7 days</b>:') in msg_mock.call_args_list[0][0][0]
|
||||
assert 'Daily Profit over the last 7 days</b>:' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_weekly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, mocker) -> None:
|
||||
default_conf['max_open_trades'] = 1
|
||||
def test_weekly_handle(default_conf_usdt, update, ticker, fee, mocker, time_machine) -> None:
|
||||
default_conf_usdt['max_open_trades'] = 1
|
||||
mocker.patch(
|
||||
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
|
||||
return_value=15000.0
|
||||
return_value=1.1
|
||||
)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -530,27 +505,10 @@ def test_weekly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
|
||||
patch_get_signal(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobjs = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobjs)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
# Move to saturday - so all trades are within that week
|
||||
time_machine.move_to('2022-06-11')
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Try valid data
|
||||
# /weekly 2
|
||||
@@ -564,10 +522,10 @@ def test_weekly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
today = datetime.utcnow().date()
|
||||
first_iso_day_of_current_week = today - timedelta(days=today.weekday())
|
||||
assert str(first_iso_day_of_current_week) in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Reset msg_mock
|
||||
msg_mock.reset_mock()
|
||||
@@ -577,44 +535,10 @@ def test_weekly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
assert "Weekly Profit over the last 8 weeks (starting from Monday)</b>:" \
|
||||
in msg_mock.call_args_list[0][0][0]
|
||||
assert 'Weekly' in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Reset msg_mock
|
||||
msg_mock.reset_mock()
|
||||
freqtradebot.config['max_open_trades'] = 2
|
||||
# Add two other trades
|
||||
n = freqtradebot.enter_positions()
|
||||
assert n == 2
|
||||
|
||||
trades = Trade.query.all()
|
||||
for trade in trades:
|
||||
trade.update_trade(oobj)
|
||||
trade.update_trade(oobjs)
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
|
||||
# /weekly 1
|
||||
# By default, the 8 previous weeks are shown
|
||||
# So the previous modified trade should be excluded from the stats
|
||||
context = MagicMock()
|
||||
context.args = ["1"]
|
||||
telegram._weekly(update=update, context=context)
|
||||
assert str(' 0.00018651 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 2.798 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 3 trades') in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_weekly_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker
|
||||
)
|
||||
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot)
|
||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Try invalid data
|
||||
msg_mock.reset_mock()
|
||||
@@ -633,16 +557,17 @@ def test_weekly_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
context = MagicMock()
|
||||
context.args = ["this week"]
|
||||
telegram._weekly(update=update, context=context)
|
||||
assert str('Weekly Profit over the last 8 weeks (starting from Monday)</b>:') \
|
||||
assert (
|
||||
'Weekly Profit over the last 8 weeks (starting from Monday)</b>:'
|
||||
in msg_mock.call_args_list[0][0][0]
|
||||
)
|
||||
|
||||
|
||||
def test_monthly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
limit_sell_order, mocker) -> None:
|
||||
default_conf['max_open_trades'] = 1
|
||||
def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker, time_machine) -> None:
|
||||
default_conf_usdt['max_open_trades'] = 1
|
||||
mocker.patch(
|
||||
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
|
||||
return_value=15000.0
|
||||
return_value=1.1
|
||||
)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -650,27 +575,10 @@ def test_monthly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
|
||||
patch_get_signal(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobjs = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobjs)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
# Move to day within the month so all mock trades fall into this week.
|
||||
time_machine.move_to('2022-06-11')
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Try valid data
|
||||
# /monthly 2
|
||||
@@ -683,10 +591,10 @@ def test_monthly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
today = datetime.utcnow().date()
|
||||
current_month = f"{today.year}-{today.month:02} "
|
||||
assert current_month in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Reset msg_mock
|
||||
msg_mock.reset_mock()
|
||||
@@ -697,24 +605,13 @@ def test_monthly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
assert 'Monthly Profit over the last 6 months</b>:' in msg_mock.call_args_list[0][0][0]
|
||||
assert 'Month ' in msg_mock.call_args_list[0][0][0]
|
||||
assert current_month in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Reset msg_mock
|
||||
msg_mock.reset_mock()
|
||||
freqtradebot.config['max_open_trades'] = 2
|
||||
# Add two other trades
|
||||
n = freqtradebot.enter_positions()
|
||||
assert n == 2
|
||||
|
||||
trades = Trade.query.all()
|
||||
for trade in trades:
|
||||
trade.update_trade(oobj)
|
||||
trade.update_trade(oobjs)
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
|
||||
# /monthly 12
|
||||
context = MagicMock()
|
||||
@@ -722,24 +619,14 @@ def test_monthly_handle(default_conf, update, ticker, limit_buy_order, fee,
|
||||
telegram._monthly(update=update, context=context)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'Monthly Profit over the last 12 months</b>:' in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00018651 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 2.798 USD') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 3 trades') in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# The one-digit months should contain a zero, Eg: September 2021 = "2021-09"
|
||||
# Since we loaded the last 12 months, any month should appear
|
||||
assert str('-09') in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_monthly_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker
|
||||
)
|
||||
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot)
|
||||
|
||||
# Try invalid data
|
||||
msg_mock.reset_mock()
|
||||
freqtradebot.state = State.RUNNING
|
||||
@@ -760,16 +647,16 @@ def test_monthly_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||
assert str('Monthly Profit over the last 6 months</b>:') in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
limit_buy_order, limit_sell_order, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
def test_profit_handle(default_conf_usdt, update, ticker_usdt, ticker_sell_up, fee,
|
||||
limit_sell_order_usdt, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=1.1)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
fetch_ticker=ticker_usdt,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
patch_get_signal(freqtradebot)
|
||||
|
||||
telegram._profit(update=update, context=MagicMock())
|
||||
@@ -781,13 +668,6 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
Trade.commit()
|
||||
|
||||
context = MagicMock()
|
||||
# Test with invalid 2nd argument (should silently pass)
|
||||
context.args = ["aaa"]
|
||||
@@ -795,15 +675,16 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'No closed trade' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0]
|
||||
mocker.patch('freqtrade.wallets.Wallets.get_starting_balance', return_value=0.01)
|
||||
assert ('∙ `-0.000005 BTC (-0.50%) (-0.0 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
mocker.patch('freqtrade.wallets.Wallets.get_starting_balance', return_value=1000)
|
||||
assert ('∙ `0.298 USDT (0.50%) (0.03 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
in msg_mock.call_args_list[-1][0][0])
|
||||
msg_mock.reset_mock()
|
||||
|
||||
# Update the ticker with a market going up
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', ticker_sell_up)
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
oobj = Order.parse_from_ccxt_object(
|
||||
limit_sell_order_usdt, limit_sell_order_usdt['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.now(timezone.utc)
|
||||
@@ -814,15 +695,15 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
telegram._profit(update=update, context=context)
|
||||
assert msg_mock.call_count == 1
|
||||
assert '*ROI:* Closed trades' in msg_mock.call_args_list[-1][0][0]
|
||||
assert ('∙ `0.00006217 BTC (6.20%) (0.62 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
assert ('∙ `5.685 USDT (9.45%) (0.57 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
in msg_mock.call_args_list[-1][0][0])
|
||||
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '∙ `6.253 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0]
|
||||
assert ('∙ `0.00006217 BTC (6.20%) (0.62 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
assert ('∙ `5.685 USDT (9.45%) (0.57 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
in msg_mock.call_args_list[-1][0][0])
|
||||
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '∙ `6.253 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
assert '*Best Performing:* `ETH/BTC: 6.20%`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Best Performing:* `ETH/USDT: 9.45%`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('is_short', [True, False])
|
||||
@@ -1365,75 +1246,43 @@ def test_force_enter_no_pair(default_conf, update, mocker) -> None:
|
||||
assert fbuy_mock.call_count == 1
|
||||
|
||||
|
||||
def test_telegram_performance_handle(default_conf, update, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, mocker) -> None:
|
||||
def test_telegram_performance_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
||||
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
get_fee=fee,
|
||||
)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
telegram._performance(update=update, context=MagicMock())
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'Performance' in msg_mock.call_args_list[0][0][0]
|
||||
assert '<code>ETH/BTC\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
assert '<code>XRP/USDT\t9.842 USDT (10.00%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_telegram_entry_tag_performance_handle(
|
||||
default_conf, update, ticker, fee, limit_buy_order, limit_sell_order, mocker) -> None:
|
||||
default_conf_usdt, update, ticker, fee, mocker) -> None:
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
get_fee=fee,
|
||||
)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
patch_get_signal(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.enter_tag = "TESTBUY"
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
context = MagicMock()
|
||||
telegram._enter_tag_performance(update=update, context=context)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'Entry Tag Performance' in msg_mock.call_args_list[0][0][0]
|
||||
assert '<code>TESTBUY\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
assert '<code>TEST1\t3.987 USDT (5.00%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
context.args = [trade.pair]
|
||||
context.args = ['XRP/USDT']
|
||||
telegram._enter_tag_performance(update=update, context=context)
|
||||
assert msg_mock.call_count == 2
|
||||
|
||||
@@ -1446,39 +1295,24 @@ def test_telegram_entry_tag_performance_handle(
|
||||
assert "Error" in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_telegram_exit_reason_performance_handle(default_conf, update, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, mocker) -> None:
|
||||
def test_telegram_exit_reason_performance_handle(default_conf_usdt, update, ticker, fee,
|
||||
mocker) -> None:
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
get_fee=fee,
|
||||
)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
patch_get_signal(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
trade.exit_reason = 'TESTSELL'
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
context = MagicMock()
|
||||
telegram._exit_reason_performance(update=update, context=context)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'Exit Reason Performance' in msg_mock.call_args_list[0][0][0]
|
||||
assert '<code>TESTSELL\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
context.args = [trade.pair]
|
||||
assert '<code>roi\t9.842 USDT (10.00%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
context.args = ['XRP/USDT']
|
||||
|
||||
telegram._exit_reason_performance(update=update, context=context)
|
||||
assert msg_mock.call_count == 2
|
||||
@@ -1492,45 +1326,27 @@ def test_telegram_exit_reason_performance_handle(default_conf, update, ticker, f
|
||||
assert "Error" in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_telegram_mix_tag_performance_handle(default_conf, update, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, mocker) -> None:
|
||||
def test_telegram_mix_tag_performance_handle(default_conf_usdt, update, ticker, fee,
|
||||
mocker) -> None:
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
get_fee=fee,
|
||||
)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
|
||||
patch_get_signal(freqtradebot)
|
||||
|
||||
# Create some test data
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
|
||||
trade.enter_tag = "TESTBUY"
|
||||
trade.exit_reason = "TESTSELL"
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
limit_buy_order['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy')
|
||||
trade.update_order(limit_buy_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
# Simulate fulfilled LIMIT_SELL order for trade
|
||||
oobj = Order.parse_from_ccxt_object(limit_sell_order, limit_sell_order['symbol'], 'sell')
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.close_date = datetime.utcnow()
|
||||
trade.is_open = False
|
||||
create_mock_trades_usdt(fee)
|
||||
|
||||
context = MagicMock()
|
||||
telegram._mix_tag_performance(update=update, context=context)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'Mix Tag Performance' in msg_mock.call_args_list[0][0][0]
|
||||
assert ('<code>TESTBUY TESTSELL\t0.00006217 BTC (6.20%) (1)</code>'
|
||||
assert ('<code>TEST3 roi\t9.842 USDT (10.00%) (1)</code>'
|
||||
in msg_mock.call_args_list[0][0][0])
|
||||
|
||||
context.args = [trade.pair]
|
||||
context.args = ['XRP/USDT']
|
||||
telegram._mix_tag_performance(update=update, context=context)
|
||||
assert msg_mock.call_count == 2
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# pragma pylint: disable=missing-docstring, C0103, protected-access
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
@@ -7,6 +8,7 @@ from requests import RequestException
|
||||
|
||||
from freqtrade.enums import ExitType, RPCMessageType
|
||||
from freqtrade.rpc import RPC
|
||||
from freqtrade.rpc.discord import Discord
|
||||
from freqtrade.rpc.webhook import Webhook
|
||||
from tests.conftest import get_patched_freqtradebot, log_has
|
||||
|
||||
@@ -406,3 +408,42 @@ def test__send_msg_with_raw_format(default_conf, mocker, caplog):
|
||||
webhook._send_msg(msg)
|
||||
|
||||
assert post.call_args[1] == {'data': msg['data'], 'headers': {'Content-Type': 'text/plain'}}
|
||||
|
||||
|
||||
def test_send_msg_discord(default_conf, mocker):
|
||||
|
||||
default_conf["discord"] = {
|
||||
'enabled': True,
|
||||
'webhook_url': "https://webhookurl..."
|
||||
}
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
||||
discord = Discord(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
||||
|
||||
msg = {
|
||||
'type': RPCMessageType.EXIT_FILL,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'ETH/BTC',
|
||||
'direction': 'Long',
|
||||
'gain': "profit",
|
||||
'close_rate': 0.005,
|
||||
'amount': 0.8,
|
||||
'order_type': 'limit',
|
||||
'open_date': datetime.now() - timedelta(days=1),
|
||||
'close_date': datetime.now(),
|
||||
'open_rate': 0.004,
|
||||
'current_rate': 0.005,
|
||||
'profit_amount': 0.001,
|
||||
'profit_ratio': 0.20,
|
||||
'stake_currency': 'BTC',
|
||||
'enter_tag': 'enter_tagggg',
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
}
|
||||
discord.send_msg(msg=msg)
|
||||
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'embeds' in msg_mock.call_args_list[0][0][0]
|
||||
assert 'title' in msg_mock.call_args_list[0][0][0]['embeds'][0]
|
||||
assert 'color' in msg_mock.call_args_list[0][0][0]['embeds'][0]
|
||||
assert 'fields' in msg_mock.call_args_list[0][0][0]['embeds'][0]
|
||||
|
||||
@@ -27,7 +27,6 @@ class HyperoptableStrategy(StrategyTestV2):
|
||||
'sell_minusdi': 0.4
|
||||
}
|
||||
|
||||
buy_rsi = IntParameter([0, 50], default=30, space='buy')
|
||||
buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy')
|
||||
sell_rsi = IntParameter(low=50, high=100, default=70, space='sell')
|
||||
sell_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell',
|
||||
@@ -45,6 +44,12 @@ class HyperoptableStrategy(StrategyTestV2):
|
||||
})
|
||||
return prot
|
||||
|
||||
def bot_start(self, **kwargs) -> None:
|
||||
"""
|
||||
Parameters can also be defined here ...
|
||||
"""
|
||||
self.buy_rsi = IntParameter([0, 50], default=30, space='buy')
|
||||
|
||||
def informative_pairs(self):
|
||||
"""
|
||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
||||
|
||||
@@ -178,8 +178,8 @@ class StrategyTestV3(IStrategy):
|
||||
return dataframe
|
||||
|
||||
def leverage(self, pair: str, current_time: datetime, current_rate: float,
|
||||
proposed_leverage: float, max_leverage: float, side: str,
|
||||
**kwargs) -> float:
|
||||
proposed_leverage: float, max_leverage: float, entry_tag: Optional[str],
|
||||
side: str, **kwargs) -> float:
|
||||
# Return 3.0 in all cases.
|
||||
# Bot-logic must make sure it's an allowed leverage and eventually adjust accordingly.
|
||||
|
||||
|
||||
@@ -16,10 +16,12 @@ from freqtrade.exceptions import OperationalException, StrategyError
|
||||
from freqtrade.optimize.space import SKDecimal
|
||||
from freqtrade.persistence import PairLocks, Trade
|
||||
from freqtrade.resolvers import StrategyResolver
|
||||
from freqtrade.strategy.hyper import detect_parameters
|
||||
from freqtrade.strategy.parameters import (BaseParameter, BooleanParameter, CategoricalParameter,
|
||||
DecimalParameter, IntParameter, RealParameter)
|
||||
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
||||
from tests.conftest import CURRENT_TEST_STRATEGY, TRADE_SIDES, log_has, log_has_re
|
||||
from tests.conftest import (CURRENT_TEST_STRATEGY, TRADE_SIDES, create_mock_trades, log_has,
|
||||
log_has_re)
|
||||
|
||||
from .strats.strategy_test_v3 import StrategyTestV3
|
||||
|
||||
@@ -614,6 +616,7 @@ def test_leverage_callback(default_conf, side) -> None:
|
||||
proposed_leverage=1.0,
|
||||
max_leverage=5.0,
|
||||
side=side,
|
||||
entry_tag=None,
|
||||
) == 1
|
||||
|
||||
default_conf['strategy'] = CURRENT_TEST_STRATEGY
|
||||
@@ -625,6 +628,7 @@ def test_leverage_callback(default_conf, side) -> None:
|
||||
proposed_leverage=1.0,
|
||||
max_leverage=5.0,
|
||||
side=side,
|
||||
entry_tag='entry_tag_test',
|
||||
) == 3
|
||||
|
||||
|
||||
@@ -809,6 +813,28 @@ def test_strategy_safe_wrapper(value):
|
||||
assert ret == value
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_strategy_safe_wrapper_trade_copy(fee):
|
||||
create_mock_trades(fee)
|
||||
|
||||
def working_method(trade):
|
||||
assert len(trade.orders) > 0
|
||||
assert trade.orders
|
||||
trade.orders = []
|
||||
assert len(trade.orders) == 0
|
||||
return trade
|
||||
|
||||
trade = Trade.get_open_trades()[0]
|
||||
# Don't assert anything before strategy_wrapper.
|
||||
# This ensures that relationship loading works correctly.
|
||||
ret = strategy_safe_wrapper(working_method, message='DeadBeef')(trade=trade)
|
||||
assert isinstance(ret, Trade)
|
||||
assert id(trade) != id(ret)
|
||||
# Did not modify the original order
|
||||
assert len(trade.orders) > 0
|
||||
assert len(ret.orders) == 0
|
||||
|
||||
|
||||
def test_hyperopt_parameters():
|
||||
from skopt.space import Categorical, Integer, Real
|
||||
with pytest.raises(OperationalException, match=r"Name is determined.*"):
|
||||
@@ -893,7 +919,7 @@ def test_auto_hyperopt_interface(default_conf):
|
||||
default_conf.update({'strategy': 'HyperoptableStrategy'})
|
||||
PairLocks.timeframe = default_conf['timeframe']
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
strategy.ft_bot_start()
|
||||
with pytest.raises(OperationalException):
|
||||
next(strategy.enumerate_parameters('deadBeef'))
|
||||
|
||||
@@ -908,15 +934,18 @@ def test_auto_hyperopt_interface(default_conf):
|
||||
assert strategy.sell_minusdi.value == 0.5
|
||||
all_params = strategy.detect_all_parameters()
|
||||
assert isinstance(all_params, dict)
|
||||
assert len(all_params['buy']) == 2
|
||||
# Only one buy param at class level
|
||||
assert len(all_params['buy']) == 1
|
||||
# Running detect params at instance level reveals both parameters.
|
||||
assert len(list(detect_parameters(strategy, 'buy'))) == 2
|
||||
assert len(all_params['sell']) == 2
|
||||
# Number of Hyperoptable parameters
|
||||
assert all_params['count'] == 6
|
||||
assert all_params['count'] == 5
|
||||
|
||||
strategy.__class__.sell_rsi = IntParameter([0, 10], default=5, space='buy')
|
||||
|
||||
with pytest.raises(OperationalException, match=r"Inconclusive parameter.*"):
|
||||
[x for x in strategy.detect_parameters('sell')]
|
||||
[x for x in detect_parameters(strategy, 'sell')]
|
||||
|
||||
|
||||
def test_auto_hyperopt_interface_loadparams(default_conf, mocker, caplog):
|
||||
|
||||
@@ -209,13 +209,14 @@ def test_edge_overrides_stoploss(limit_order, fee, caplog, mocker,
|
||||
#
|
||||
# mocking the ticker: price is falling ...
|
||||
enter_price = limit_order['buy']['price']
|
||||
ticker_val = {
|
||||
'bid': enter_price,
|
||||
'ask': enter_price,
|
||||
'last': enter_price,
|
||||
}
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=MagicMock(return_value={
|
||||
'bid': enter_price * buy_price_mult,
|
||||
'ask': enter_price * buy_price_mult,
|
||||
'last': enter_price * buy_price_mult,
|
||||
}),
|
||||
fetch_ticker=MagicMock(return_value=ticker_val),
|
||||
get_fee=fee,
|
||||
)
|
||||
#############################################
|
||||
@@ -228,11 +229,12 @@ def test_edge_overrides_stoploss(limit_order, fee, caplog, mocker,
|
||||
freqtrade.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
caplog.clear()
|
||||
limit_order['buy']['id'] = trade.orders[0].order_id
|
||||
oobj = Order.parse_from_ccxt_object(limit_order['buy'], 'NEO/BTC', 'buy')
|
||||
trade.update_order(limit_order['buy'])
|
||||
trade.update_trade(oobj)
|
||||
#############################################
|
||||
ticker_val.update({
|
||||
'bid': enter_price * buy_price_mult,
|
||||
'ask': enter_price * buy_price_mult,
|
||||
'last': enter_price * buy_price_mult,
|
||||
})
|
||||
|
||||
# stoploss shoud be hit
|
||||
assert freqtrade.handle_trade(trade) is not ignore_strat_sl
|
||||
@@ -1776,9 +1778,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
|
||||
'type': 'stop_loss_limit',
|
||||
'price': 3,
|
||||
'average': 2,
|
||||
'info': {
|
||||
'stopPrice': '2.178'
|
||||
}
|
||||
'stopPrice': '2.178'
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', stoploss_order_hanging)
|
||||
@@ -2577,6 +2577,7 @@ def test_check_handle_cancelled_buy(
|
||||
get_fee=fee
|
||||
)
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
open_trade.orders = []
|
||||
open_trade.is_short = is_short
|
||||
Trade.query.session.add(open_trade)
|
||||
|
||||
@@ -2961,6 +2962,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
freqtrade._notify_enter_cancel = MagicMock()
|
||||
|
||||
# TODO: Convert to real trade
|
||||
trade = MagicMock()
|
||||
trade.pair = 'LTC/USDT'
|
||||
trade.open_rate = 200
|
||||
@@ -2968,6 +2970,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_
|
||||
trade.entry_side = "buy"
|
||||
l_order['filled'] = 0.0
|
||||
l_order['status'] = 'open'
|
||||
trade.nr_of_successful_entries = 0
|
||||
reason = CANCEL_REASON['TIMEOUT']
|
||||
assert freqtrade.handle_cancel_enter(trade, l_order, reason)
|
||||
assert cancel_order_mock.call_count == 1
|
||||
@@ -3010,7 +3013,9 @@ def test_handle_cancel_enter_exchanges(mocker, caplog, default_conf_usdt, is_sho
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
|
||||
reason = CANCEL_REASON['TIMEOUT']
|
||||
# TODO: Convert to real trade
|
||||
trade = MagicMock()
|
||||
trade.nr_of_successful_entries = 0
|
||||
trade.pair = 'LTC/ETH'
|
||||
trade.entry_side = "sell" if is_short else "buy"
|
||||
assert freqtrade.handle_cancel_enter(trade, limit_buy_order_canceled_empty, reason)
|
||||
@@ -3043,13 +3048,14 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order
|
||||
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
freqtrade._notify_enter_cancel = MagicMock()
|
||||
|
||||
# TODO: Convert to real trade
|
||||
trade = MagicMock()
|
||||
trade.pair = 'LTC/USDT'
|
||||
trade.entry_side = "buy"
|
||||
trade.open_rate = 200
|
||||
trade.entry_side = "buy"
|
||||
trade.open_order_id = "open_order_noop"
|
||||
trade.nr_of_successful_entries = 0
|
||||
l_order['filled'] = 0.0
|
||||
l_order['status'] = 'open'
|
||||
reason = CANCEL_REASON['TIMEOUT']
|
||||
@@ -3783,6 +3789,7 @@ def test_exit_profit_only(
|
||||
trade = Trade.query.first()
|
||||
assert trade.is_short == is_short
|
||||
oobj = Order.parse_from_ccxt_object(limit_order[eside], limit_order[eside]['symbol'], eside)
|
||||
trade.update_order(limit_order[eside])
|
||||
trade.update_trade(oobj)
|
||||
freqtrade.wallets.update()
|
||||
if profit_only:
|
||||
@@ -4071,6 +4078,7 @@ def test_trailing_stop_loss_positive(
|
||||
trade = Trade.query.first()
|
||||
assert trade.is_short == is_short
|
||||
oobj = Order.parse_from_ccxt_object(limit_order[eside], limit_order[eside]['symbol'], eside)
|
||||
trade.update_order(limit_order[eside])
|
||||
trade.update_trade(oobj)
|
||||
caplog.set_level(logging.DEBUG)
|
||||
# stop-loss not reached
|
||||
@@ -4816,10 +4824,19 @@ def test_startup_update_open_orders(mocker, default_conf_usdt, fee, caplog, is_s
|
||||
assert len(Order.get_open_orders()) == 2
|
||||
|
||||
caplog.clear()
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order', side_effect=InvalidOrderException)
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order', side_effect=ExchangeError)
|
||||
freqtrade.startup_update_open_orders()
|
||||
assert log_has_re(r"Error updating Order .*", caplog)
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order', side_effect=InvalidOrderException)
|
||||
hto_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_timedout_order')
|
||||
# Orders which are no longer found after X days should be assumed as canceled.
|
||||
freqtrade.startup_update_open_orders()
|
||||
assert log_has_re(r"Order is older than \d days.*", caplog)
|
||||
assert hto_mock.call_count == 2
|
||||
assert hto_mock.call_args_list[0][0][0]['status'] == 'canceled'
|
||||
assert hto_mock.call_args_list[1][0][0]['status'] == 'canceled'
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
|
||||
Reference in New Issue
Block a user