Merge branch 'sam_5889' into todo-rpc

This commit is contained in:
aezo.teo 2021-11-14 13:26:32 +08:00
commit 8f66d8f942
14 changed files with 73 additions and 61 deletions

View File

@ -33,9 +33,10 @@ class Binance(Exchange):
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
# TradingMode.SPOT always supported and not required in this list
# (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported
# TODO-lev: Uncomment once supported
# (TradingMode.MARGIN, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.ISOLATED)
]
@property

View File

@ -27,6 +27,7 @@ class Bybit(Exchange):
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
# TradingMode.SPOT always supported and not required in this list
# (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported
# TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.ISOLATED)
]

View File

@ -25,8 +25,9 @@ class Ftx(Exchange):
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
# TradingMode.SPOT always supported and not required in this list
# (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.CROSS) # TODO-lev: Uncomment once supported
# TODO-lev: Uncomment once supported
# (TradingMode.MARGIN, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.CROSS)
]
def market_is_tradable(self, market: Dict[str, Any]) -> bool:

View File

@ -30,9 +30,10 @@ class Gateio(Exchange):
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
# TradingMode.SPOT always supported and not required in this list
# (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported
# TODO-lev: Uncomment once supported
# (TradingMode.MARGIN, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.ISOLATED)
]
@property

View File

@ -27,8 +27,9 @@ class Kraken(Exchange):
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
# TradingMode.SPOT always supported and not required in this list
# (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.CROSS) # TODO-lev: No CCXT support
# TODO-lev: Uncomment once supported
# (TradingMode.MARGIN, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.CROSS)
]
def market_is_tradable(self, market: Dict[str, Any]) -> bool:

View File

@ -21,9 +21,10 @@ class Okex(Exchange):
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
# TradingMode.SPOT always supported and not required in this list
# (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported
# (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported
# TODO-lev: Uncomment once supported
# (TradingMode.MARGIN, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.CROSS),
# (TradingMode.FUTURES, Collateral.ISOLATED)
]
@property

View File

@ -922,8 +922,7 @@ class FreqtradeBot(LoggingMixin):
Check if trade is fulfilled in which case the stoploss
on exchange should be added immediately if stoploss on exchange
is enabled.
# TODO-lev: liquidation price will always be on exchange, even though
# TODO-lev: stoploss_on_exchange might not be enabled
# TODO-lev: liquidation price always on exchange, even without stoploss_on_exchange
"""
logger.debug('Handling stoploss on exchange %s ...', trade)
@ -1517,7 +1516,7 @@ class FreqtradeBot(LoggingMixin):
self.wallets.update()
if fee_abs != 0 and self.wallets.get_free(trade_base_currency) >= amount:
# Eat into dust if we own more than base currency
# TODO-lev: won't be in base currency for shorts
# TODO-lev: settle currency for futures
logger.info(f"Fee amount for {trade} was in base currency - "
f"Eating Fee {fee_abs} into dust.")
elif fee_abs != 0:

View File

@ -916,8 +916,8 @@ class Trade(_DECL_BASE, LocalTrade):
max_rate = Column(Float, nullable=True, default=0.0)
# Lowest price reached
min_rate = Column(Float, nullable=True)
sell_reason = Column(String(100), nullable=True) # TODO-lev: Change to close_reason
sell_order_status = Column(String(100), nullable=True) # TODO-lev: Change to close_order_status
sell_reason = Column(String(100), nullable=True)
sell_order_status = Column(String(100), nullable=True)
strategy = Column(String(100), nullable=True)
buy_tag = Column(String(100), nullable=True)
timeframe = Column(Integer, nullable=True)

View File

@ -32,7 +32,7 @@ class StoplossGuard(IProtection):
def _reason(self) -> str:
"""
LockReason to use
#TODO-lev: check if min is the right word for shorts
# TODO-lev: check if min is the right word for shorts
"""
return (f'{self._trade_limit} stoplosses in {self._lookback_period} min, '
f'locking for {self._stop_duration} min.')

View File

@ -488,7 +488,7 @@ def leverage_trade(fee):
open_order_id='dry_run_leverage_buy_12368',
strategy='DefaultStrategy',
timeframe=5,
sell_reason='sell_signal', # TODO-lev: Update to exit/close reason
sell_reason='sell_signal',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=300),
close_date=datetime.now(tz=timezone.utc),
interest_rate=0.0005

View File

@ -586,10 +586,10 @@ def test_api_trades(botclient, mocker, fee, markets, is_short):
assert rc.json()['total_trades'] == 2
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
def test_api_trade_single(botclient, mocker, fee, ticker, markets):
@pytest.mark.parametrize('is_short', [True, False])
def test_api_trade_single(botclient, mocker, fee, ticker, markets, is_short):
ftbot, client = botclient
patch_get_signal(ftbot)
patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=markets),
@ -599,7 +599,7 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets):
assert_response(rc, 404)
assert rc.json()['detail'] == 'Trade not found.'
create_mock_trades(fee, False)
create_mock_trades(fee, is_short=is_short)
Trade.query.session.flush()
rc = client_get(client, f"{BASE_URI}/trade/3")
@ -607,10 +607,10 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets):
assert rc.json()['trade_id'] == 3
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
def test_api_delete_trade(botclient, mocker, fee, markets):
@pytest.mark.parametrize('is_short', [True, False])
def test_api_delete_trade(botclient, mocker, fee, markets, is_short):
ftbot, client = botclient
patch_get_signal(ftbot)
patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short)
stoploss_mock = MagicMock()
cancel_mock = MagicMock()
mocker.patch.multiple(
@ -749,10 +749,10 @@ def test_api_profit(botclient, mocker, ticker, fee, markets):
}
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
def test_api_stats(botclient, mocker, ticker, fee, markets,):
@pytest.mark.parametrize('is_short', [True, False])
def test_api_stats(botclient, mocker, ticker, fee, markets, is_short):
ftbot, client = botclient
patch_get_signal(ftbot)
patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
@ -766,7 +766,7 @@ def test_api_stats(botclient, mocker, ticker, fee, markets,):
assert 'durations' in rc.json()
assert 'sell_reasons' in rc.json()
create_mock_trades(fee, False)
create_mock_trades(fee, is_short=is_short)
rc = client_get(client, f"{BASE_URI}/stats")
assert_response(rc, 200)

View File

@ -1294,8 +1294,8 @@ def test_telegram_trades(mocker, update, default_conf, fee):
msg_mock.call_args_list[0][0][0]))
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
def test_telegram_delete_trade(mocker, update, default_conf, fee):
@pytest.mark.parametrize('is_short', [True, False])
def test_telegram_delete_trade(mocker, update, default_conf, fee, is_short):
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
context = MagicMock()
@ -1305,7 +1305,7 @@ def test_telegram_delete_trade(mocker, update, default_conf, fee):
assert "Trade-id not set." in msg_mock.call_args_list[0][0][0]
msg_mock.reset_mock()
create_mock_trades(fee, False)
create_mock_trades(fee, is_short)
context = MagicMock()
context.args = [1]

View File

@ -1,5 +1,6 @@
from datetime import datetime
import pytest
from pandas import DataFrame
from freqtrade.persistence.models import Trade
@ -16,7 +17,11 @@ def test_strategy_test_v2_structure():
assert hasattr(StrategyTestV3, 'populate_sell_trend')
def test_strategy_test_v2(result, fee):
@pytest.mark.parametrize('is_short,side', [
(True, 'short'),
(False, 'long'),
])
def test_strategy_test_v2(result, fee, is_short, side):
strategy = StrategyTestV3({})
metadata = {'pair': 'ETH/BTC'}
@ -32,16 +37,18 @@ def test_strategy_test_v2(result, fee):
open_rate=19_000,
amount=0.1,
pair='ETH/BTC',
fee_open=fee.return_value
fee_open=fee.return_value,
is_short=is_short
)
assert strategy.confirm_trade_entry(pair='ETH/BTC', order_type='limit', amount=0.1,
rate=20000, time_in_force='gtc',
current_time=datetime.utcnow(), side='long') is True
current_time=datetime.utcnow(),
side=side) is True
assert strategy.confirm_trade_exit(pair='ETH/BTC', trade=trade, order_type='limit', amount=0.1,
rate=20000, time_in_force='gtc', sell_reason='roi',
current_time=datetime.utcnow()) is True
current_time=datetime.utcnow(),
side=side) is True
# TODO-lev: Test for shorts?
assert strategy.custom_stoploss(pair='ETH/BTC', trade=trade, current_time=datetime.now(),
current_rate=20_000, current_profit=0.05) == strategy.stoploss

View File

@ -1907,12 +1907,12 @@ def test_get_total_closed_profit(fee, use_db):
@pytest.mark.usefixtures("init_persistence")
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
@pytest.mark.parametrize('is_short', [True, False])
@pytest.mark.parametrize('use_db', [True, False])
def test_get_trades_proxy(fee, use_db):
def test_get_trades_proxy(fee, use_db, is_short):
Trade.use_db = use_db
Trade.reset_trades()
create_mock_trades(fee, False, use_db)
create_mock_trades(fee, is_short, use_db)
trades = Trade.get_trades_proxy()
assert len(trades) == 6
@ -2042,48 +2042,48 @@ def test_update_order_from_ccxt(caplog):
@pytest.mark.usefixtures("init_persistence")
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
def test_select_order(fee):
create_mock_trades(fee, False)
@pytest.mark.parametrize('is_short', [True, False])
def test_select_order(fee, is_short):
create_mock_trades(fee, is_short)
trades = Trade.get_trades().all()
# Open buy order, no sell order
order = trades[0].select_order('buy', True)
order = trades[0].select_order(trades[0].enter_side, True)
assert order is None
order = trades[0].select_order('buy', False)
order = trades[0].select_order(trades[0].enter_side, False)
assert order is not None
order = trades[0].select_order('sell', None)
order = trades[0].select_order(trades[0].exit_side, None)
assert order is None
# closed buy order, and open sell order
order = trades[1].select_order('buy', True)
order = trades[1].select_order(trades[1].enter_side, True)
assert order is None
order = trades[1].select_order('buy', False)
order = trades[1].select_order(trades[1].enter_side, False)
assert order is not None
order = trades[1].select_order('buy', None)
order = trades[1].select_order(trades[1].enter_side, None)
assert order is not None
order = trades[1].select_order('sell', True)
order = trades[1].select_order(trades[1].exit_side, True)
assert order is None
order = trades[1].select_order('sell', False)
order = trades[1].select_order(trades[1].exit_side, False)
assert order is not None
# Has open buy order
order = trades[3].select_order('buy', True)
order = trades[3].select_order(trades[3].enter_side, True)
assert order is not None
order = trades[3].select_order('buy', False)
order = trades[3].select_order(trades[3].enter_side, False)
assert order is None
# Open sell order
order = trades[4].select_order('buy', True)
order = trades[4].select_order(trades[4].enter_side, True)
assert order is None
order = trades[4].select_order('buy', False)
order = trades[4].select_order(trades[4].enter_side, False)
assert order is not None
order = trades[4].select_order('sell', True)
order = trades[4].select_order(trades[4].exit_side, True)
assert order is not None
assert order.ft_order_side == 'stoploss'
order = trades[4].select_order('sell', False)
order = trades[4].select_order(trades[4].exit_side, False)
assert order is None