|
|
|
@ -10,6 +10,7 @@ from unittest.mock import ANY, MagicMock, PropertyMock, patch
|
|
|
|
|
import arrow
|
|
|
|
|
import pytest
|
|
|
|
|
from pandas import DataFrame
|
|
|
|
|
from sqlalchemy import select
|
|
|
|
|
|
|
|
|
|
from freqtrade.constants import CANCEL_REASON, UNLIMITED_STAKE_AMOUNT
|
|
|
|
|
from freqtrade.enums import (CandleType, ExitCheckTuple, ExitType, RPCMessageType, RunMode,
|
|
|
|
@ -247,7 +248,7 @@ def test_edge_overrides_stoploss(limit_order, fee, caplog, mocker,
|
|
|
|
|
patch_get_signal(freqtrade)
|
|
|
|
|
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
caplog.clear()
|
|
|
|
|
#############################################
|
|
|
|
|
ticker_val.update({
|
|
|
|
@ -278,7 +279,7 @@ def test_total_open_trades_stakes(mocker, default_conf_usdt, ticker_usdt, fee) -
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
patch_get_signal(freqtrade)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
|
|
|
|
|
assert trade is not None
|
|
|
|
|
assert trade.stake_amount == 60.0
|
|
|
|
@ -286,7 +287,7 @@ def test_total_open_trades_stakes(mocker, default_conf_usdt, ticker_usdt, fee) -
|
|
|
|
|
assert trade.open_date is not None
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.order_by(Trade.id.desc()).first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade).order_by(Trade.id.desc())).first()
|
|
|
|
|
|
|
|
|
|
assert trade is not None
|
|
|
|
|
assert trade.stake_amount == 60.0
|
|
|
|
@ -317,7 +318,7 @@ def test_create_trade(default_conf_usdt, ticker_usdt, limit_order,
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
freqtrade.create_trade('ETH/USDT')
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade is not None
|
|
|
|
|
assert pytest.approx(trade.stake_amount) == 60.0
|
|
|
|
@ -568,12 +569,12 @@ def test_process_trade_creation(default_conf_usdt, ticker_usdt, limit_order, lim
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
|
|
|
|
|
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
|
|
|
|
|
trades = Trade.get_open_trades()
|
|
|
|
|
assert not trades
|
|
|
|
|
|
|
|
|
|
freqtrade.process()
|
|
|
|
|
|
|
|
|
|
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
|
|
|
|
|
trades = Trade.get_open_trades()
|
|
|
|
|
assert len(trades) == 1
|
|
|
|
|
trade = trades[0]
|
|
|
|
|
assert trade is not None
|
|
|
|
@ -640,11 +641,11 @@ def test_process_trade_handling(default_conf_usdt, ticker_usdt, limit_buy_order_
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
patch_get_signal(freqtrade)
|
|
|
|
|
|
|
|
|
|
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
|
|
|
|
|
trades = Trade.get_open_trades()
|
|
|
|
|
assert not trades
|
|
|
|
|
freqtrade.process()
|
|
|
|
|
|
|
|
|
|
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
|
|
|
|
|
trades = Trade.get_open_trades()
|
|
|
|
|
assert len(trades) == 1
|
|
|
|
|
|
|
|
|
|
# Nothing happened ...
|
|
|
|
@ -671,7 +672,7 @@ def test_process_trade_no_whitelist_pair(default_conf_usdt, ticker_usdt, limit_b
|
|
|
|
|
assert pair not in default_conf_usdt['exchange']['pair_whitelist']
|
|
|
|
|
|
|
|
|
|
# create open trade not in whitelist
|
|
|
|
|
Trade.query.session.add(Trade(
|
|
|
|
|
Trade.session.add(Trade(
|
|
|
|
|
pair=pair,
|
|
|
|
|
stake_amount=0.001,
|
|
|
|
|
fee_open=fee.return_value,
|
|
|
|
@ -681,7 +682,7 @@ def test_process_trade_no_whitelist_pair(default_conf_usdt, ticker_usdt, limit_b
|
|
|
|
|
open_rate=0.01,
|
|
|
|
|
exchange='binance',
|
|
|
|
|
))
|
|
|
|
|
Trade.query.session.add(Trade(
|
|
|
|
|
Trade.session.add(Trade(
|
|
|
|
|
pair='ETH/USDT',
|
|
|
|
|
stake_amount=0.001,
|
|
|
|
|
fee_open=fee.return_value,
|
|
|
|
@ -838,7 +839,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
|
|
|
|
|
# Should create an open trade with an open order id
|
|
|
|
|
# As the order is not fulfilled yet
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
@ -865,7 +866,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
|
|
|
|
|
mocker.patch(f'{EXMS}.create_order', MagicMock(return_value=order))
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
|
|
|
|
trade = Trade.query.all()[2]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[2]
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -883,7 +884,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
order['id'] = '555'
|
|
|
|
|
mocker.patch(f'{EXMS}.create_order', MagicMock(return_value=order))
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount)
|
|
|
|
|
trade = Trade.query.all()[3]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[3]
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -896,7 +897,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
|
|
|
|
|
freqtrade.strategy.custom_stake_amount = lambda **kwargs: 150.0
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
|
|
|
|
trade = Trade.query.all()[4]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[4]
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert pytest.approx(trade.stake_amount) == 150
|
|
|
|
@ -905,7 +906,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
order['id'] = '557'
|
|
|
|
|
freqtrade.strategy.custom_stake_amount = lambda **kwargs: 20 / 0
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
|
|
|
|
trade = Trade.query.all()[5]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[5]
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert pytest.approx(trade.stake_amount) == 2.0
|
|
|
|
@ -934,7 +935,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
order['id'] = '5566'
|
|
|
|
|
freqtrade.strategy.custom_entry_price = lambda **kwargs: 0.508
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
|
|
|
|
trade = Trade.query.all()[6]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[6]
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_rate_requested == 0.508
|
|
|
|
@ -951,7 +952,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
|
|
|
|
trade = Trade.query.all()[7]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[7]
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_rate_requested == 10
|
|
|
|
@ -961,7 +962,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
order['id'] = '5568'
|
|
|
|
|
freqtrade.strategy.custom_entry_price = lambda **kwargs: "string price"
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
|
|
|
|
trade = Trade.query.all()[8]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[8]
|
|
|
|
|
# Trade(id=9, pair=ETH/USDT, amount=0.20000000, is_short=False,
|
|
|
|
|
# leverage=1.0, open_rate=10.00000000, open_since=...)
|
|
|
|
|
# Trade(id=9, pair=ETH/USDT, amount=0.60000000, is_short=True,
|
|
|
|
@ -982,7 +983,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
freqtrade.exchange.get_max_pair_stake_amount = MagicMock(return_value=500)
|
|
|
|
|
|
|
|
|
|
assert freqtrade.execute_entry(pair, 2000, is_short=is_short)
|
|
|
|
|
trade = Trade.query.all()[9]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[9]
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert pytest.approx(trade.stake_amount) == 500
|
|
|
|
|
|
|
|
|
@ -991,7 +992,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
freqtrade.strategy.leverage.reset_mock()
|
|
|
|
|
assert freqtrade.execute_entry(pair, 200, leverage_=3)
|
|
|
|
|
assert freqtrade.strategy.leverage.call_count == 0
|
|
|
|
|
trade = Trade.query.all()[10]
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).all()[10]
|
|
|
|
|
assert trade.leverage == 1 if trading_mode == 'spot' else 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1053,7 +1054,7 @@ def test_execute_entry_min_leverage(mocker, default_conf_usdt, fee, limit_order,
|
|
|
|
|
freqtrade.strategy.leverage = MagicMock(return_value=5.0)
|
|
|
|
|
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade.leverage == 5.0
|
|
|
|
|
# assert trade.stake_amount == 2
|
|
|
|
|
|
|
|
|
@ -1158,7 +1159,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
|
|
|
|
|
# as a trade actually happened
|
|
|
|
|
caplog.clear()
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
trade.open_order_id = None
|
|
|
|
@ -1271,7 +1272,7 @@ def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog,
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
trade.open_order_id = None
|
|
|
|
@ -1316,7 +1317,7 @@ def test_create_stoploss_order_invalid_order(
|
|
|
|
|
freqtrade.strategy.order_types['stoploss_on_exchange'] = True
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
caplog.clear()
|
|
|
|
|
freqtrade.create_stoploss_order(trade, 200)
|
|
|
|
@ -1367,7 +1368,7 @@ def test_create_stoploss_order_insufficient_funds(
|
|
|
|
|
freqtrade.strategy.order_types['stoploss_on_exchange'] = True
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
caplog.clear()
|
|
|
|
|
freqtrade.create_stoploss_order(trade, 200)
|
|
|
|
@ -1435,7 +1436,7 @@ def test_handle_stoploss_on_exchange_trailing(
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
trade.open_order_id = None
|
|
|
|
@ -1554,7 +1555,7 @@ def test_handle_stoploss_on_exchange_trailing_error(
|
|
|
|
|
freqtrade.strategy.order_types['stoploss_on_exchange_interval'] = 60
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
trade.open_order_id = None
|
|
|
|
@ -1668,7 +1669,7 @@ def test_handle_stoploss_on_exchange_custom_stop(
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
trade.open_order_id = None
|
|
|
|
@ -1796,7 +1797,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, limit_orde
|
|
|
|
|
freqtrade.active_pair_whitelist = freqtrade.edge.adjust(freqtrade.active_pair_whitelist)
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
trade.open_order_id = None
|
|
|
|
|
trade.stoploss_order_id = 100
|
|
|
|
@ -2162,7 +2163,7 @@ def test_handle_trade(
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
@ -2217,7 +2218,7 @@ def test_handle_overlapping_signals(
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
# Buy and Sell triggering, so doing nothing ...
|
|
|
|
|
trades = Trade.query.all()
|
|
|
|
|
trades = Trade.session.scalars(select(Trade)).all()
|
|
|
|
|
|
|
|
|
|
nb_trades = len(trades)
|
|
|
|
|
assert nb_trades == 0
|
|
|
|
@ -2225,7 +2226,7 @@ def test_handle_overlapping_signals(
|
|
|
|
|
# Buy is triggering, so buying ...
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trades = Trade.query.all()
|
|
|
|
|
trades = Trade.session.scalars(select(Trade)).all()
|
|
|
|
|
for trade in trades:
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
nb_trades = len(trades)
|
|
|
|
@ -2235,7 +2236,7 @@ def test_handle_overlapping_signals(
|
|
|
|
|
# Buy and Sell are not triggering, so doing nothing ...
|
|
|
|
|
patch_get_signal(freqtrade, enter_long=False)
|
|
|
|
|
assert freqtrade.handle_trade(trades[0]) is False
|
|
|
|
|
trades = Trade.query.all()
|
|
|
|
|
trades = Trade.session.scalars(select(Trade)).all()
|
|
|
|
|
for trade in trades:
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
nb_trades = len(trades)
|
|
|
|
@ -2248,7 +2249,7 @@ def test_handle_overlapping_signals(
|
|
|
|
|
else:
|
|
|
|
|
patch_get_signal(freqtrade, enter_long=True, exit_long=True)
|
|
|
|
|
assert freqtrade.handle_trade(trades[0]) is False
|
|
|
|
|
trades = Trade.query.all()
|
|
|
|
|
trades = Trade.session.scalars(select(Trade)).all()
|
|
|
|
|
for trade in trades:
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
nb_trades = len(trades)
|
|
|
|
@ -2260,7 +2261,7 @@ def test_handle_overlapping_signals(
|
|
|
|
|
patch_get_signal(freqtrade, enter_long=False, exit_short=True)
|
|
|
|
|
else:
|
|
|
|
|
patch_get_signal(freqtrade, enter_long=False, exit_long=True)
|
|
|
|
|
trades = Trade.query.all()
|
|
|
|
|
trades = Trade.session.scalars(select(Trade)).all()
|
|
|
|
|
for trade in trades:
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert freqtrade.handle_trade(trades[0]) is True
|
|
|
|
@ -2291,7 +2292,7 @@ def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_order_open, fee,
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
|
|
|
|
@ -2333,7 +2334,7 @@ def test_handle_trade_use_exit_signal(
|
|
|
|
|
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
|
|
|
|
@ -2370,7 +2371,7 @@ def test_close_trade(
|
|
|
|
|
# Create trade and sell it
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
@ -2427,7 +2428,7 @@ def test_manage_open_orders_entry_usercustom(
|
|
|
|
|
open_trade.is_short = is_short
|
|
|
|
|
open_trade.orders[0].side = 'sell' if is_short else 'buy'
|
|
|
|
|
open_trade.orders[0].ft_order_side = 'sell' if is_short else 'buy'
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
# Ensure default is to return empty (so not mocked yet)
|
|
|
|
@ -2438,7 +2439,8 @@ def test_manage_open_orders_entry_usercustom(
|
|
|
|
|
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False)
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
assert cancel_order_mock.call_count == 0
|
|
|
|
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
|
|
|
|
trades = Trade.session.scalars(
|
|
|
|
|
select(Trade).filter(Trade.open_order_id.is_(open_trade.open_order_id))).all()
|
|
|
|
|
nb_trades = len(trades)
|
|
|
|
|
assert nb_trades == 1
|
|
|
|
|
assert freqtrade.strategy.check_entry_timeout.call_count == 1
|
|
|
|
@ -2446,7 +2448,8 @@ def test_manage_open_orders_entry_usercustom(
|
|
|
|
|
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
assert cancel_order_mock.call_count == 0
|
|
|
|
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
|
|
|
|
trades = Trade.session.scalars(
|
|
|
|
|
select(Trade).filter(Trade.open_order_id.is_(open_trade.open_order_id))).all()
|
|
|
|
|
nb_trades = len(trades)
|
|
|
|
|
assert nb_trades == 1
|
|
|
|
|
assert freqtrade.strategy.check_entry_timeout.call_count == 1
|
|
|
|
@ -2456,7 +2459,8 @@ def test_manage_open_orders_entry_usercustom(
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
assert cancel_order_wr_mock.call_count == 1
|
|
|
|
|
assert rpc_mock.call_count == 2
|
|
|
|
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
|
|
|
|
trades = Trade.session.scalars(
|
|
|
|
|
select(Trade).filter(Trade.open_order_id.is_(open_trade.open_order_id))).all()
|
|
|
|
|
nb_trades = len(trades)
|
|
|
|
|
assert nb_trades == 0
|
|
|
|
|
assert freqtrade.strategy.check_entry_timeout.call_count == 1
|
|
|
|
@ -2486,7 +2490,7 @@ def test_manage_open_orders_entry(
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
|
|
|
|
|
open_trade.is_short = is_short
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False)
|
|
|
|
@ -2524,7 +2528,7 @@ def test_adjust_entry_cancel(
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
open_trade.is_short = is_short
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
# Timeout to not interfere
|
|
|
|
@ -2535,7 +2539,7 @@ def test_adjust_entry_cancel(
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
|
|
|
|
assert len(trades) == 0
|
|
|
|
|
assert len(Order.query.all()) == 0
|
|
|
|
|
assert len(Order.session.scalars(select(Order)).all()) == 0
|
|
|
|
|
assert log_has_re(
|
|
|
|
|
f"{'Sell' if is_short else 'Buy'} order user requested order cancel*", caplog)
|
|
|
|
|
assert log_has_re(
|
|
|
|
@ -2565,7 +2569,7 @@ def test_adjust_entry_maintain_replace(
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
open_trade.is_short = is_short
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
# Timeout to not interfere
|
|
|
|
@ -2586,7 +2590,7 @@ def test_adjust_entry_maintain_replace(
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
|
|
|
|
assert len(trades) == 1
|
|
|
|
|
nb_all_orders = len(Order.query.all())
|
|
|
|
|
nb_all_orders = len(Order.session.scalars(select(Order)).all())
|
|
|
|
|
assert nb_all_orders == 2
|
|
|
|
|
# New order seems to be in closed status?
|
|
|
|
|
# nb_open_orders = len(Order.get_open_orders())
|
|
|
|
@ -2618,7 +2622,7 @@ def test_check_handle_cancelled_buy(
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
open_trade.orders = []
|
|
|
|
|
open_trade.is_short = is_short
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
# check it does cancel buy orders over the time limit
|
|
|
|
@ -2649,7 +2653,7 @@ def test_manage_open_orders_buy_exception(
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
|
|
|
|
|
open_trade.is_short = is_short
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
# check it does cancel buy orders over the time limit
|
|
|
|
@ -2691,7 +2695,7 @@ def test_manage_open_orders_exit_usercustom(
|
|
|
|
|
open_trade_usdt.close_date = arrow.utcnow().shift(minutes=-601).datetime
|
|
|
|
|
open_trade_usdt.close_profit_abs = 0.001
|
|
|
|
|
|
|
|
|
|
Trade.query.session.add(open_trade_usdt)
|
|
|
|
|
Trade.session.add(open_trade_usdt)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
# Ensure default is false
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
@ -2771,7 +2775,7 @@ def test_manage_open_orders_exit(
|
|
|
|
|
open_trade_usdt.close_profit_abs = 0.001
|
|
|
|
|
open_trade_usdt.is_short = is_short
|
|
|
|
|
|
|
|
|
|
Trade.query.session.add(open_trade_usdt)
|
|
|
|
|
Trade.session.add(open_trade_usdt)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
freqtrade.strategy.check_exit_timeout = MagicMock(return_value=False)
|
|
|
|
@ -2811,7 +2815,7 @@ def test_check_handle_cancelled_exit(
|
|
|
|
|
open_trade_usdt.close_date = arrow.utcnow().shift(minutes=-601).datetime
|
|
|
|
|
open_trade_usdt.is_short = is_short
|
|
|
|
|
|
|
|
|
|
Trade.query.session.add(open_trade_usdt)
|
|
|
|
|
Trade.session.add(open_trade_usdt)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
# check it does cancel sell orders over the time limit
|
|
|
|
@ -2848,7 +2852,7 @@ def test_manage_open_orders_partial(
|
|
|
|
|
)
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
prior_stake = open_trade.stake_amount
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
# check it does cancel buy orders over the time limit
|
|
|
|
@ -2893,7 +2897,7 @@ def test_manage_open_orders_partial_fee(
|
|
|
|
|
|
|
|
|
|
open_trade.fee_open = fee()
|
|
|
|
|
open_trade.fee_close = fee()
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
# cancelling a half-filled order should update the amount to the bought amount
|
|
|
|
|
# and apply fees if necessary.
|
|
|
|
@ -2943,7 +2947,7 @@ def test_manage_open_orders_partial_except(
|
|
|
|
|
|
|
|
|
|
open_trade.fee_open = fee()
|
|
|
|
|
open_trade.fee_close = fee()
|
|
|
|
|
Trade.query.session.add(open_trade)
|
|
|
|
|
Trade.session.add(open_trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
# cancelling a half-filled order should update the amount to the bought amount
|
|
|
|
|
# and apply fees if necessary.
|
|
|
|
@ -2982,7 +2986,7 @@ def test_manage_open_orders_exception(default_conf_usdt, ticker_usdt, open_trade
|
|
|
|
|
)
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
|
|
|
|
|
Trade.query.session.add(open_trade_usdt)
|
|
|
|
|
Trade.session.add(open_trade_usdt)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
caplog.clear()
|
|
|
|
@ -3011,7 +3015,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_
|
|
|
|
|
freqtrade._notify_enter_cancel = MagicMock()
|
|
|
|
|
|
|
|
|
|
trade = mock_trade_usdt_4(fee, is_short)
|
|
|
|
|
Trade.query.session.add(trade)
|
|
|
|
|
Trade.session.add(trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
|
|
|
|
|
l_order['filled'] = 0.0
|
|
|
|
@ -3061,7 +3065,7 @@ def test_handle_cancel_enter_exchanges(mocker, caplog, default_conf_usdt, is_sho
|
|
|
|
|
reason = CANCEL_REASON['TIMEOUT']
|
|
|
|
|
|
|
|
|
|
trade = mock_trade_usdt_4(fee, is_short)
|
|
|
|
|
Trade.query.session.add(trade)
|
|
|
|
|
Trade.session.add(trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
assert freqtrade.handle_cancel_enter(trade, limit_buy_order_canceled_empty, reason)
|
|
|
|
|
assert cancel_order_mock.call_count == 0
|
|
|
|
@ -3095,7 +3099,7 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order
|
|
|
|
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
|
|
|
|
freqtrade._notify_enter_cancel = MagicMock()
|
|
|
|
|
trade = mock_trade_usdt_4(fee, is_short)
|
|
|
|
|
Trade.query.session.add(trade)
|
|
|
|
|
Trade.session.add(trade)
|
|
|
|
|
Trade.commit()
|
|
|
|
|
l_order['filled'] = 0.0
|
|
|
|
|
l_order['status'] = 'open'
|
|
|
|
@ -3261,7 +3265,7 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
rpc_mock.reset_mock()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade.is_short == is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert freqtrade.strategy.confirm_trade_exit.call_count == 0
|
|
|
|
@ -3342,7 +3346,7 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd
|
|
|
|
|
# Create some test data
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
@ -3415,7 +3419,7 @@ def test_execute_trade_exit_custom_exit_price(
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
rpc_mock.reset_mock()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert freqtrade.strategy.confirm_trade_exit.call_count == 0
|
|
|
|
@ -3492,7 +3496,7 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run(
|
|
|
|
|
# Create some test data
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade.is_short == is_short
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
@ -3566,7 +3570,7 @@ def test_execute_trade_exit_sloe_cancel_exception(
|
|
|
|
|
patch_get_signal(freqtrade)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
PairLock.session = MagicMock()
|
|
|
|
|
|
|
|
|
|
freqtrade.config['dry_run'] = False
|
|
|
|
@ -3611,7 +3615,7 @@ def test_execute_trade_exit_with_stoploss_on_exchange(
|
|
|
|
|
# Create some test data
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
trades = [trade]
|
|
|
|
@ -3631,7 +3635,7 @@ def test_execute_trade_exit_with_stoploss_on_exchange(
|
|
|
|
|
exit_check=ExitCheckTuple(exit_type=ExitType.STOP_LOSS)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
assert cancel_order.call_count == 1
|
|
|
|
@ -3669,7 +3673,7 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(
|
|
|
|
|
# Create some test data
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trades = [trade]
|
|
|
|
|
assert trade.stoploss_order_id is None
|
|
|
|
|
|
|
|
|
@ -3755,7 +3759,7 @@ def test_execute_trade_exit_market_order(
|
|
|
|
|
# Create some test data
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
@ -3830,7 +3834,7 @@ def test_execute_trade_exit_insufficient_funds_error(default_conf_usdt, ticker_u
|
|
|
|
|
# Create some test data
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
@ -3898,7 +3902,7 @@ def test_exit_profit_only(
|
|
|
|
|
exit_type=ExitType.NONE))
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).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])
|
|
|
|
@ -3941,7 +3945,7 @@ def test_sell_not_enough_balance(default_conf_usdt, limit_order, limit_order_ope
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
amnt = trade.amount
|
|
|
|
|
|
|
|
|
|
oobj = Order.parse_from_ccxt_object(limit_order['buy'], limit_order['buy']['symbol'], 'buy')
|
|
|
|
@ -4009,7 +4013,7 @@ def test_locked_pairs(default_conf_usdt, ticker_usdt, fee,
|
|
|
|
|
# Create some test data
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
@ -4064,7 +4068,7 @@ def test_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limit_order_
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
oobj = Order.parse_from_ccxt_object(
|
|
|
|
|
limit_order[eside], limit_order[eside]['symbol'], eside)
|
|
|
|
@ -4114,7 +4118,7 @@ def test_trailing_stop_loss(default_conf_usdt, limit_order_open,
|
|
|
|
|
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade.is_short == is_short
|
|
|
|
|
assert freqtrade.handle_trade(trade) is False
|
|
|
|
|
|
|
|
|
@ -4189,7 +4193,7 @@ def test_trailing_stop_loss_positive(
|
|
|
|
|
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).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])
|
|
|
|
@ -4286,7 +4290,7 @@ def test_disable_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limi
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
|
|
|
|
|
oobj = Order.parse_from_ccxt_object(
|
|
|
|
@ -4752,7 +4756,7 @@ def test_order_book_depth_of_market(
|
|
|
|
|
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
if is_high_delta:
|
|
|
|
|
assert trade is None
|
|
|
|
|
else:
|
|
|
|
@ -4763,7 +4767,7 @@ def test_order_book_depth_of_market(
|
|
|
|
|
assert trade.open_date is not None
|
|
|
|
|
assert trade.exchange == 'binance'
|
|
|
|
|
|
|
|
|
|
assert len(Trade.query.all()) == 1
|
|
|
|
|
assert len(Trade.session.scalars(select(Trade)).all()) == 1
|
|
|
|
|
|
|
|
|
|
# Simulate fulfilled LIMIT_BUY order for trade
|
|
|
|
|
oobj = Order.parse_from_ccxt_object(
|
|
|
|
@ -4860,7 +4864,7 @@ def test_order_book_exit_pricing(
|
|
|
|
|
|
|
|
|
|
freqtrade.enter_positions()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
|
|
|
|
|
time.sleep(0.01) # Race condition fix
|
|
|
|
@ -4932,7 +4936,7 @@ def test_sync_wallet_dry_run(mocker, default_conf_usdt, ticker_usdt, fee, limit_
|
|
|
|
|
|
|
|
|
|
n = bot.enter_positions()
|
|
|
|
|
assert n == 2
|
|
|
|
|
trades = Trade.query.all()
|
|
|
|
|
trades = Trade.session.scalars(select(Trade)).all()
|
|
|
|
|
assert len(trades) == 2
|
|
|
|
|
|
|
|
|
|
bot.config['max_open_trades'] = 3
|
|
|
|
@ -4965,7 +4969,7 @@ def test_cancel_all_open_orders(mocker, default_conf_usdt, fee, limit_order, lim
|
|
|
|
|
|
|
|
|
|
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
|
|
|
|
create_mock_trades(fee, is_short=is_short)
|
|
|
|
|
trades = Trade.query.all()
|
|
|
|
|
trades = Trade.session.scalars(select(Trade)).all()
|
|
|
|
|
assert len(trades) == MOCK_TRADE_COUNT
|
|
|
|
|
freqtrade.cancel_all_open_orders()
|
|
|
|
|
assert buy_mock.call_count == buy_calls
|
|
|
|
@ -4981,7 +4985,7 @@ def test_check_for_open_trades(mocker, default_conf_usdt, fee, is_short):
|
|
|
|
|
assert freqtrade.rpc.send_msg.call_count == 0
|
|
|
|
|
|
|
|
|
|
create_mock_trades(fee, is_short)
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
trade.is_short = is_short
|
|
|
|
|
trade.is_open = True
|
|
|
|
|
|
|
|
|
@ -5149,7 +5153,7 @@ def test_reupdate_enter_order_fees(mocker, default_conf_usdt, fee, caplog, is_sh
|
|
|
|
|
exchange='binance',
|
|
|
|
|
is_short=is_short
|
|
|
|
|
)
|
|
|
|
|
Trade.query.session.add(trade)
|
|
|
|
|
Trade.session.add(trade)
|
|
|
|
|
|
|
|
|
|
freqtrade.handle_insufficient_funds(trade)
|
|
|
|
|
# assert log_has_re(r"Trying to reupdate buy fees for .*", caplog)
|
|
|
|
@ -5546,10 +5550,10 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount)
|
|
|
|
|
# Should create an closed trade with an no open order id
|
|
|
|
|
# Order is filled and trade is open
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 1
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -5559,7 +5563,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
# Assume it does nothing since order is closed and trade is open
|
|
|
|
|
freqtrade.update_trades_without_assigned_fees()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -5569,7 +5573,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -5595,10 +5599,10 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
mocker.patch(f'{EXMS}.fetch_order_or_stoploss_order', MagicMock(return_value=open_dca_order_1))
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, trade=trade)
|
|
|
|
|
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 2
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id == '651'
|
|
|
|
|
assert trade.open_rate == 11
|
|
|
|
@ -5628,14 +5632,14 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
mocker.patch(f'{EXMS}.fetch_order_or_stoploss_order', fetch_order_mm)
|
|
|
|
|
freqtrade.update_trades_without_assigned_fees()
|
|
|
|
|
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 2
|
|
|
|
|
# Assert that the trade is found as open and without fees
|
|
|
|
|
trades: List[Trade] = Trade.get_open_trades_without_assigned_fees()
|
|
|
|
|
assert len(trades) == 1
|
|
|
|
|
# Assert trade is as expected
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id == '651'
|
|
|
|
|
assert trade.open_rate == 11
|
|
|
|
@ -5672,14 +5676,14 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
|
|
|
|
|
# Assert trade is as expected (averaged dca)
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
|
assert pytest.approx(trade.open_rate) == 9.90909090909
|
|
|
|
|
assert trade.amount == 22
|
|
|
|
|
assert pytest.approx(trade.stake_amount) == 218
|
|
|
|
|
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 2
|
|
|
|
|
|
|
|
|
@ -5714,14 +5718,14 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
assert freqtrade.execute_entry(pair, stake_amount, trade=trade)
|
|
|
|
|
|
|
|
|
|
# Assert trade is as expected (averaged dca)
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
|
assert pytest.approx(trade.open_rate) == 8.729729729729
|
|
|
|
|
assert trade.amount == 37
|
|
|
|
|
assert trade.stake_amount == 323
|
|
|
|
|
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 3
|
|
|
|
|
|
|
|
|
@ -5752,7 +5756,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
sub_trade_amt=15)
|
|
|
|
|
|
|
|
|
|
# Assert trade is as expected (averaged dca)
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
|
assert trade.is_open
|
|
|
|
@ -5760,7 +5764,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
assert trade.stake_amount == 192.05405405405406
|
|
|
|
|
assert pytest.approx(trade.open_rate) == 8.729729729729
|
|
|
|
|
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 4
|
|
|
|
|
|
|
|
|
@ -5825,10 +5829,10 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
assert freqtrade.execute_entry(pair, amount)
|
|
|
|
|
# Should create an closed trade with an no open order id
|
|
|
|
|
# Order is filled and trade is open
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 1
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -5838,7 +5842,7 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
# Assume it does nothing since order is closed and trade is open
|
|
|
|
|
freqtrade.update_trades_without_assigned_fees()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -5848,7 +5852,7 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
|
|
|
|
|
freqtrade.manage_open_orders()
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
@ -5884,7 +5888,7 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
assert len(trades) == 1
|
|
|
|
|
# Assert trade is as expected (averaged dca)
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
|
assert trade.amount == 50
|
|
|
|
@ -5893,7 +5897,7 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
assert pytest.approx(trade.realized_profit) == -152.375
|
|
|
|
|
assert pytest.approx(trade.close_profit_abs) == -152.375
|
|
|
|
|
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 2
|
|
|
|
|
# Make sure the closed order is found as the second order.
|
|
|
|
@ -5926,7 +5930,7 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
sub_trade_amt=amount)
|
|
|
|
|
# Assert trade is as expected (averaged dca)
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
|
assert trade.amount == 50
|
|
|
|
@ -5935,7 +5939,7 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
|
|
|
|
|
# Trade fully realized
|
|
|
|
|
assert pytest.approx(trade.realized_profit) == 94.25
|
|
|
|
|
assert pytest.approx(trade.close_profit_abs) == 94.25
|
|
|
|
|
orders = Order.query.all()
|
|
|
|
|
orders = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders
|
|
|
|
|
assert len(orders) == 3
|
|
|
|
|
|
|
|
|
@ -6020,11 +6024,11 @@ def test_position_adjust3(mocker, default_conf_usdt, fee, data) -> None:
|
|
|
|
|
exit_check=ExitCheckTuple(exit_type=ExitType.PARTIAL_EXIT),
|
|
|
|
|
sub_trade_amt=amount)
|
|
|
|
|
|
|
|
|
|
orders1 = Order.query.all()
|
|
|
|
|
orders1 = Order.session.scalars(select(Order)).all()
|
|
|
|
|
assert orders1
|
|
|
|
|
assert len(orders1) == idx + 1
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
if idx < len(data) - 1:
|
|
|
|
|
assert trade.is_open is True
|
|
|
|
@ -6039,7 +6043,7 @@ def test_position_adjust3(mocker, default_conf_usdt, fee, data) -> None:
|
|
|
|
|
order_obj = trade.select_order(order[0], False)
|
|
|
|
|
assert order_obj.order_id == f'60{idx}'
|
|
|
|
|
|
|
|
|
|
trade = Trade.query.first()
|
|
|
|
|
trade = Trade.session.scalars(select(Trade)).first()
|
|
|
|
|
assert trade
|
|
|
|
|
assert trade.open_order_id is None
|
|
|
|
|
assert trade.is_open is False
|
|
|
|
|