diff --git a/config_examples/config_full.example.json b/config_examples/config_full.example.json
index 85c1bde5b..1fb2817b8 100644
--- a/config_examples/config_full.example.json
+++ b/config_examples/config_full.example.json
@@ -61,8 +61,8 @@
"stoploss_on_exchange_interval": 60
},
"order_time_in_force": {
- "buy": "gtc",
- "sell": "gtc"
+ "entry": "gtc",
+ "exit": "gtc"
},
"pairlists": [
{"method": "StaticPairList"},
diff --git a/docs/configuration.md b/docs/configuration.md
index 7a42966b0..99c13ca5a 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -122,7 +122,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `ignore_roi_if_buy_signal` | Do not sell if the buy signal is still active. This setting takes preference over `minimal_roi` and `use_sell_signal`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean
| `ignore_buying_expired_candle_after` | Specifies the number of seconds until a buy signal is no longer used.
**Datatype:** Integer
| `order_types` | Configure order-types depending on the action (`"buy"`, `"sell"`, `"stoploss"`, `"stoploss_on_exchange"`). [More information below](#understand-order_types). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict
-| `order_time_in_force` | Configure time in force for buy and sell orders. [More information below](#understand-order_time_in_force). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict
+| `order_time_in_force` | Configure time in force for entry and exit orders. [More information below](#understand-order_time_in_force). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict
| `custom_price_max_distance_ratio` | Configure maximum distance ratio between current and custom entry or exit price.
*Defaults to `0.02` 2%).*
**Datatype:** Positive float
| `exchange.name` | **Required.** Name of the exchange class to use. [List below](#user-content-what-values-for-exchangename).
**Datatype:** String
| `exchange.sandbox` | Use the 'sandbox' version of the exchange, where the exchange provides a sandbox for risk-free integration. See [here](sandbox-testing.md) in more details.
**Datatype:** Boolean
@@ -465,8 +465,8 @@ The possible values are: `gtc` (default), `fok` or `ioc`.
``` python
"order_time_in_force": {
- "buy": "gtc",
- "sell": "gtc"
+ "entry": "gtc",
+ "exit": "gtc"
},
```
diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py
index 85ff4408f..87a309f12 100644
--- a/freqtrade/configuration/config_validation.py
+++ b/freqtrade/configuration/config_validation.py
@@ -6,7 +6,7 @@ from jsonschema import Draft4Validator, validators
from jsonschema.exceptions import ValidationError, best_match
from freqtrade import constants
-from freqtrade.enums import RunMode
+from freqtrade.enums import RunMode, TradingMode
from freqtrade.exceptions import OperationalException
@@ -80,6 +80,7 @@ def validate_config_consistency(conf: Dict[str, Any]) -> None:
_validate_protections(conf)
_validate_unlimited_amount(conf)
_validate_ask_orderbook(conf)
+ validate_migrated_strategy_settings(conf)
# validate configuration before returning
logger.info('Validating configuration ...')
@@ -207,3 +208,24 @@ def _validate_ask_orderbook(conf: Dict[str, Any]) -> None:
"Please use `order_book_top` instead of `order_book_min` and `order_book_max` "
"for your `ask_strategy` configuration."
)
+
+
+def validate_migrated_strategy_settings(conf: Dict[str, Any]) -> None:
+
+ _validate_time_in_force(conf)
+
+
+def _validate_time_in_force(conf: Dict[str, Any]) -> None:
+
+ time_in_force = conf.get('order_time_in_force', {})
+ if 'buy' in time_in_force or 'sell' in time_in_force:
+ if conf.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT:
+ raise OperationalException(
+ "Please migrate your time_in_force settings to use 'entry' and 'exit'.")
+ else:
+ logger.warning(
+ "DEPRECATED: Using 'buy' and 'sell' for time_in_force is deprecated."
+ "Please migrate your time_in_force settings to use 'entry' and 'exit'."
+ )
+ time_in_force['entry'] = time_in_force.pop('buy')
+ time_in_force['exit'] = time_in_force.pop('sell')
diff --git a/freqtrade/constants.py b/freqtrade/constants.py
index cc4a14a2b..bafda93db 100644
--- a/freqtrade/constants.py
+++ b/freqtrade/constants.py
@@ -19,7 +19,7 @@ DEFAULT_DB_PROD_URL = 'sqlite:///tradesv3.sqlite'
DEFAULT_DB_DRYRUN_URL = 'sqlite:///tradesv3.dryrun.sqlite'
UNLIMITED_STAKE_AMOUNT = 'unlimited'
DEFAULT_AMOUNT_RESERVE_PERCENT = 0.05
-REQUIRED_ORDERTIF = ['buy', 'sell']
+REQUIRED_ORDERTIF = ['entry', 'exit']
REQUIRED_ORDERTYPES = ['buy', 'sell', 'stoploss', 'stoploss_on_exchange']
ORDERBOOK_SIDES = ['ask', 'bid']
ORDERTYPE_POSSIBILITIES = ['limit', 'market']
@@ -233,10 +233,10 @@ CONF_SCHEMA = {
'order_time_in_force': {
'type': 'object',
'properties': {
- 'buy': {'type': 'string', 'enum': ORDERTIF_POSSIBILITIES},
- 'sell': {'type': 'string', 'enum': ORDERTIF_POSSIBILITIES}
+ 'entry': {'type': 'string', 'enum': ORDERTIF_POSSIBILITIES},
+ 'exit': {'type': 'string', 'enum': ORDERTIF_POSSIBILITIES}
},
- 'required': ['buy', 'sell']
+ 'required': REQUIRED_ORDERTIF
},
'exchange': {'$ref': '#/definitions/exchange'},
'edge': {'$ref': '#/definitions/edge'},
diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py
index 45c18378d..4f3f723c0 100644
--- a/freqtrade/freqtradebot.py
+++ b/freqtrade/freqtradebot.py
@@ -595,7 +595,7 @@ class FreqtradeBot(LoggingMixin):
:param leverage: amount of leverage applied to this trade
:return: True if a buy order is created, false if it fails.
"""
- time_in_force = self.strategy.order_time_in_force['buy']
+ time_in_force = self.strategy.order_time_in_force['entry']
[side, name] = ['sell', 'Short'] if is_short else ['buy', 'Long']
trade_side = 'short' if is_short else 'long'
@@ -659,13 +659,12 @@ class FreqtradeBot(LoggingMixin):
amount_requested = amount
if order_status == 'expired' or order_status == 'rejected':
- order_tif = self.strategy.order_time_in_force['buy']
# return false if the order is not filled
if float(order['filled']) == 0:
- logger.warning('%s %s order with time in force %s for %s is %s by %s.'
- ' zero amount is fulfilled.',
- name, order_tif, order_type, pair, order_status, self.exchange.name)
+ logger.warning(f'{name} {time_in_force} order with time in force {order_type} '
+ f'for {pair} is {order_status} by {self.exchange.name}.'
+ ' zero amount is fulfilled.')
return False
else:
# the order is partially fulfilled
@@ -673,8 +672,9 @@ class FreqtradeBot(LoggingMixin):
# if the order is fulfilled fully or partially
logger.warning('%s %s order with time in force %s for %s is %s by %s.'
' %s amount fulfilled out of %s (%s remaining which is canceled).',
- name, order_tif, order_type, pair, order_status, self.exchange.name,
- order['filled'], order['amount'], order['remaining']
+ name, time_in_force, order_type, pair, order_status,
+ self.exchange.name, order['filled'], order['amount'],
+ order['remaining']
)
stake_amount = order['cost']
amount = safe_value_fallback(order, 'filled', 'amount')
@@ -725,7 +725,7 @@ class FreqtradeBot(LoggingMixin):
leverage=leverage,
is_short=is_short,
interest_rate=interest_rate,
- isolated_liq=isolated_liq,
+ liquidation_price=isolated_liq,
trading_mode=self.trading_mode,
funding_fees=funding_fees
)
@@ -1382,7 +1382,7 @@ class FreqtradeBot(LoggingMixin):
order_type = self.strategy.order_types.get("emergencysell", "market")
amount = self._safe_exit_amount(trade.pair, trade.amount)
- time_in_force = self.strategy.order_time_in_force['sell']
+ time_in_force = self.strategy.order_time_in_force['exit']
if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)(
pair=trade.pair, trade=trade, order_type=order_type, amount=amount, rate=limit,
diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py
index 2b5b4ee14..9523ca92f 100644
--- a/freqtrade/optimize/backtesting.py
+++ b/freqtrade/optimize/backtesting.py
@@ -506,7 +506,7 @@ class Backtesting:
# freqtrade does not support this in live, and the order would fill immediately
closerate = max(closerate, sell_row[LOW_IDX])
# Confirm trade exit:
- time_in_force = self.strategy.order_time_in_force['sell']
+ time_in_force = self.strategy.order_time_in_force['exit']
if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)(
pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount,
@@ -642,7 +642,7 @@ class Backtesting:
# If not pos adjust, trade is None
return trade
order_type = self.strategy.order_types['buy']
- time_in_force = self.strategy.order_time_in_force['buy']
+ time_in_force = self.strategy.order_time_in_force['entry']
if not pos_adjust:
max_leverage = self.exchange.get_max_leverage(pair, stake_amount)
diff --git a/freqtrade/persistence/migrations.py b/freqtrade/persistence/migrations.py
index 08eb9563b..112538570 100644
--- a/freqtrade/persistence/migrations.py
+++ b/freqtrade/persistence/migrations.py
@@ -82,7 +82,8 @@ def migrate_trades_and_orders_table(
# Leverage Properties
leverage = get_column_def(cols, 'leverage', '1.0')
- isolated_liq = get_column_def(cols, 'isolated_liq', 'null')
+ liquidation_price = get_column_def(cols, 'liquidation_price',
+ get_column_def(cols, 'isolated_liq', 'null'))
# sqlite does not support literals for booleans
is_short = get_column_def(cols, 'is_short', '0')
@@ -137,7 +138,7 @@ def migrate_trades_and_orders_table(
stoploss_order_id, stoploss_last_update,
max_rate, min_rate, sell_reason, sell_order_status, strategy, enter_tag,
timeframe, open_trade_value, close_profit_abs,
- trading_mode, leverage, isolated_liq, is_short,
+ trading_mode, leverage, liquidation_price, is_short,
interest_rate, funding_fees
)
select id, lower(exchange), pair,
@@ -155,7 +156,7 @@ def migrate_trades_and_orders_table(
{sell_order_status} sell_order_status,
{strategy} strategy, {enter_tag} enter_tag, {timeframe} timeframe,
{open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs,
- {trading_mode} trading_mode, {leverage} leverage, {isolated_liq} isolated_liq,
+ {trading_mode} trading_mode, {leverage} leverage, {liquidation_price} liquidation_price,
{is_short} is_short, {interest_rate} interest_rate,
{funding_fees} funding_fees
from {trade_back_name}
@@ -233,10 +234,9 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
# Check if migration necessary
# Migrates both trades and orders table!
- # if not has_column(cols, 'buy_tag'):
- if ('orders' not in previous_tables
- or not has_column(cols_orders, 'ft_fee_base')
- or not has_column(cols_orders, 'leverage')):
+ # if ('orders' not in previous_tables
+ # or not has_column(cols_orders, 'leverage')):
+ if not has_column(cols, 'liquidation_price'):
logger.info(f"Running database migration for trades - "
f"backup: {table_back_name}, {order_table_bak_name}")
migrate_trades_and_orders_table(
diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py
index 565ece5a4..b80d75dc0 100644
--- a/freqtrade/persistence/models.py
+++ b/freqtrade/persistence/models.py
@@ -329,7 +329,7 @@ class LocalTrade():
trading_mode: TradingMode = TradingMode.SPOT
# Leverage trading properties
- isolated_liq: Optional[float] = None
+ liquidation_price: Optional[float] = None
is_short: bool = False
leverage: float = 1.0
@@ -483,7 +483,7 @@ class LocalTrade():
'leverage': self.leverage,
'interest_rate': self.interest_rate,
- 'isolated_liq': self.isolated_liq,
+ 'liquidation_price': self.liquidation_price,
'is_short': self.is_short,
'trading_mode': self.trading_mode,
'funding_fees': self.funding_fees,
@@ -507,25 +507,25 @@ class LocalTrade():
self.max_rate = max(current_price, self.max_rate or self.open_rate)
self.min_rate = min(current_price_low, self.min_rate or self.open_rate)
- def set_isolated_liq(self, isolated_liq: Optional[float]):
+ def set_isolated_liq(self, liquidation_price: Optional[float]):
"""
Method you should use to set self.liquidation price.
Assures stop_loss is not passed the liquidation price
"""
- if not isolated_liq:
+ if not liquidation_price:
return
- self.isolated_liq = isolated_liq
+ self.liquidation_price = liquidation_price
def _set_stop_loss(self, stop_loss: float, percent: float):
"""
Method you should use to set self.stop_loss.
Assures stop_loss is not passed the liquidation price
"""
- if self.isolated_liq is not None:
+ if self.liquidation_price is not None:
if self.is_short:
- sl = min(stop_loss, self.isolated_liq)
+ sl = min(stop_loss, self.liquidation_price)
else:
- sl = max(stop_loss, self.isolated_liq)
+ sl = max(stop_loss, self.liquidation_price)
else:
sl = stop_loss
@@ -553,13 +553,13 @@ class LocalTrade():
if self.is_short:
new_loss = float(current_price * (1 + abs(stoploss / leverage)))
# If trading with leverage, don't set the stoploss below the liquidation price
- if self.isolated_liq:
- new_loss = min(self.isolated_liq, new_loss)
+ if self.liquidation_price:
+ new_loss = min(self.liquidation_price, new_loss)
else:
new_loss = float(current_price * (1 - abs(stoploss / leverage)))
# If trading with leverage, don't set the stoploss below the liquidation price
- if self.isolated_liq:
- new_loss = max(self.isolated_liq, new_loss)
+ if self.liquidation_price:
+ new_loss = max(self.liquidation_price, new_loss)
# no stop loss assigned yet
if self.initial_stop_loss_pct is None:
@@ -1093,7 +1093,7 @@ class Trade(_DECL_BASE, LocalTrade):
# Leverage trading properties
leverage = Column(Float, nullable=True, default=1.0)
is_short = Column(Boolean, nullable=False, default=False)
- isolated_liq = Column(Float, nullable=True)
+ liquidation_price = Column(Float, nullable=True)
# Margin Trading Properties
interest_rate = Column(Float, nullable=False, default=0.0)
diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py
index fc4b71f1a..8dee459ba 100644
--- a/freqtrade/resolvers/strategy_resolver.py
+++ b/freqtrade/resolvers/strategy_resolver.py
@@ -10,6 +10,7 @@ from inspect import getfullargspec
from pathlib import Path
from typing import Any, Dict, Optional
+from freqtrade.configuration.config_validation import validate_migrated_strategy_settings
from freqtrade.constants import REQUIRED_ORDERTIF, REQUIRED_ORDERTYPES, USERPATH_STRATEGIES
from freqtrade.exceptions import OperationalException
from freqtrade.resolvers import IResolver
@@ -160,10 +161,12 @@ class StrategyResolver(IResolver):
@staticmethod
def _strategy_sanity_validations(strategy):
+ # Ensure necessary migrations are performed first.
+ validate_migrated_strategy_settings(strategy.config)
+
if not all(k in strategy.order_types for k in REQUIRED_ORDERTYPES):
raise ImportError(f"Impossible to load Strategy '{strategy.__class__.__name__}'. "
f"Order-types mapping is incomplete.")
-
if not all(k in strategy.order_time_in_force for k in REQUIRED_ORDERTIF):
raise ImportError(f"Impossible to load Strategy '{strategy.__class__.__name__}'. "
f"Order-time-in-force mapping is incomplete.")
diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py
index 92ea3daba..e5b583a9e 100644
--- a/freqtrade/strategy/interface.py
+++ b/freqtrade/strategy/interface.py
@@ -96,8 +96,8 @@ class IStrategy(ABC, HyperStrategyMixin):
# Optional time in force
order_time_in_force: Dict = {
- 'buy': 'gtc',
- 'sell': 'gtc',
+ 'entry': 'gtc',
+ 'exit': 'gtc',
}
# run "populate_indicators" only for new candle
diff --git a/freqtrade/templates/base_strategy.py.j2 b/freqtrade/templates/base_strategy.py.j2
index 06abecc42..701909bf6 100644
--- a/freqtrade/templates/base_strategy.py.j2
+++ b/freqtrade/templates/base_strategy.py.j2
@@ -83,8 +83,8 @@ class {{ strategy }}(IStrategy):
# Optional order time in force.
order_time_in_force = {
- 'buy': 'gtc',
- 'sell': 'gtc'
+ 'entry': 'gtc',
+ 'exit': 'gtc'
}
{{ plot_config | indent(4) }}
diff --git a/freqtrade/templates/sample_short_strategy.py b/freqtrade/templates/sample_short_strategy.py
index bcb6c921e..c33327715 100644
--- a/freqtrade/templates/sample_short_strategy.py
+++ b/freqtrade/templates/sample_short_strategy.py
@@ -84,8 +84,8 @@ class SampleShortStrategy(IStrategy):
# Optional order time in force.
order_time_in_force = {
- 'buy': 'gtc',
- 'sell': 'gtc'
+ 'entry': 'gtc',
+ 'exit': 'gtc'
}
plot_config = {
diff --git a/freqtrade/templates/sample_strategy.py b/freqtrade/templates/sample_strategy.py
index 13df9c2a8..b3f1ae1c8 100644
--- a/freqtrade/templates/sample_strategy.py
+++ b/freqtrade/templates/sample_strategy.py
@@ -85,8 +85,8 @@ class SampleStrategy(IStrategy):
# Optional order time in force.
order_time_in_force = {
- 'buy': 'gtc',
- 'sell': 'gtc'
+ 'entry': 'gtc',
+ 'exit': 'gtc'
}
plot_config = {
diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py
index da8751566..ec77d1cbf 100644
--- a/tests/optimize/test_backtesting.py
+++ b/tests/optimize/test_backtesting.py
@@ -319,6 +319,7 @@ def test_backtesting_init_no_timeframe(mocker, default_conf, caplog) -> None:
del default_conf['timeframe']
default_conf['strategy_list'] = [CURRENT_TEST_STRATEGY,
'SampleStrategy']
+ # TODO: This refers to the sampleStrategy in user_data if it exists...
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
with pytest.raises(OperationalException):
@@ -613,7 +614,7 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
# = 0.0008176703703703704
trade = backtesting._enter_trade(pair, row=row, direction='long')
- assert pytest.approx(trade.isolated_liq) == 0.00081767037
+ assert pytest.approx(trade.liquidation_price) == 0.00081767037
# Binance, Short
# liquidation_price
@@ -625,7 +626,7 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
# = 0.0011787191419141915
trade = backtesting._enter_trade(pair, row=row, direction='short')
- assert pytest.approx(trade.isolated_liq) == 0.0011787191
+ assert pytest.approx(trade.liquidation_price) == 0.0011787191
# Stake-amount too high!
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=600.0)
diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py
index ce881bcf1..7e34506d6 100644
--- a/tests/rpc/test_rpc.py
+++ b/tests/rpc/test_rpc.py
@@ -112,7 +112,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'exchange': 'binance',
'leverage': 1.0,
'interest_rate': 0.0,
- 'isolated_liq': None,
+ 'liquidation_price': None,
'is_short': False,
'funding_fees': 0.0,
'trading_mode': TradingMode.SPOT,
@@ -194,7 +194,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'exchange': 'binance',
'leverage': 1.0,
'interest_rate': 0.0,
- 'isolated_liq': None,
+ 'liquidation_price': None,
'is_short': False,
'funding_fees': 0.0,
'trading_mode': TradingMode.SPOT,
diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py
index b634ec2f7..4050dcbdb 100644
--- a/tests/rpc/test_rpc_apiserver.py
+++ b/tests/rpc/test_rpc_apiserver.py
@@ -633,9 +633,6 @@ def test_api_delete_trade(botclient, mocker, fee, markets, is_short):
cancel_order=cancel_mock,
cancel_stoploss_order=stoploss_mock,
)
- rc = client_delete(client, f"{BASE_URI}/trades/1")
- # Error - trade won't exist yet.
- assert_response(rc, 502)
create_mock_trades(fee, is_short=is_short)
@@ -664,6 +661,10 @@ def test_api_delete_trade(botclient, mocker, fee, markets, is_short):
assert len(trades) - 2 == len(Trade.query.all())
assert stoploss_mock.call_count == 1
+ rc = client_delete(client, f"{BASE_URI}/trades/502")
+ # Error - trade won't exist.
+ assert_response(rc, 502)
+
def test_api_logs(botclient):
ftbot, client = botclient
diff --git a/tests/strategy/strats/hyperoptable_strategy.py b/tests/strategy/strats/hyperoptable_strategy.py
index 1126bd6cf..e843f6b58 100644
--- a/tests/strategy/strats/hyperoptable_strategy.py
+++ b/tests/strategy/strats/hyperoptable_strategy.py
@@ -45,8 +45,8 @@ class HyperoptableStrategy(IStrategy):
# Optional time in force for orders
order_time_in_force = {
- 'buy': 'gtc',
- 'sell': 'gtc',
+ 'entry': 'gtc',
+ 'exit': 'gtc',
}
buy_params = {
diff --git a/tests/strategy/strats/strategy_test_v2.py b/tests/strategy/strats/strategy_test_v2.py
index 59f1f569e..fd70cf346 100644
--- a/tests/strategy/strats/strategy_test_v2.py
+++ b/tests/strategy/strats/strategy_test_v2.py
@@ -47,8 +47,8 @@ class StrategyTestV2(IStrategy):
# Optional time in force for orders
order_time_in_force = {
- 'buy': 'gtc',
- 'sell': 'gtc',
+ 'entry': 'gtc',
+ 'exit': 'gtc',
}
# By default this strategy does not use Position Adjustments
diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py
index 0b73c1271..962fd02e9 100644
--- a/tests/strategy/strats/strategy_test_v3.py
+++ b/tests/strategy/strats/strategy_test_v3.py
@@ -48,8 +48,8 @@ class StrategyTestV3(IStrategy):
# Optional time in force for orders
order_time_in_force = {
- 'buy': 'gtc',
- 'sell': 'gtc',
+ 'entry': 'gtc',
+ 'exit': 'gtc',
}
buy_params = {
diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py
index da4f8fb78..8f407396c 100644
--- a/tests/strategy/test_strategy_loading.py
+++ b/tests/strategy/test_strategy_loading.py
@@ -257,8 +257,8 @@ def test_strategy_override_order_tif(caplog, default_conf):
caplog.set_level(logging.INFO)
order_time_in_force = {
- 'buy': 'fok',
- 'sell': 'gtc',
+ 'entry': 'fok',
+ 'exit': 'gtc',
}
default_conf.update({
@@ -268,15 +268,15 @@ def test_strategy_override_order_tif(caplog, default_conf):
strategy = StrategyResolver.load_strategy(default_conf)
assert strategy.order_time_in_force
- for method in ['buy', 'sell']:
+ for method in ['entry', 'exit']:
assert strategy.order_time_in_force[method] == order_time_in_force[method]
assert log_has("Override strategy 'order_time_in_force' with value in config file:"
- " {'buy': 'fok', 'sell': 'gtc'}.", caplog)
+ " {'entry': 'fok', 'exit': 'gtc'}.", caplog)
default_conf.update({
'strategy': CURRENT_TEST_STRATEGY,
- 'order_time_in_force': {'buy': 'fok'}
+ 'order_time_in_force': {'entry': 'fok'}
})
# Raise error for invalid configuration
with pytest.raises(ImportError,
diff --git a/tests/test_configuration.py b/tests/test_configuration.py
index 935421409..e2ab3c9b5 100644
--- a/tests/test_configuration.py
+++ b/tests/test_configuration.py
@@ -941,6 +941,28 @@ def test_validate_ask_orderbook(default_conf, caplog) -> None:
validate_config_consistency(conf)
+def test_validate_time_in_force(default_conf, caplog) -> None:
+ conf = deepcopy(default_conf)
+ conf['order_time_in_force'] = {
+ 'buy': 'gtc',
+ 'sell': 'gtc',
+ }
+ validate_config_consistency(conf)
+ assert log_has_re(r"DEPRECATED: Using 'buy' and 'sell' for time_in_force is.*", caplog)
+ assert conf['order_time_in_force']['entry'] == 'gtc'
+ assert conf['order_time_in_force']['exit'] == 'gtc'
+
+ conf = deepcopy(default_conf)
+ conf['order_time_in_force'] = {
+ 'buy': 'gtc',
+ 'sell': 'gtc',
+ }
+ conf['trading_mode'] = 'futures'
+ with pytest.raises(OperationalException,
+ match=r"Please migrate your time_in_force settings .* 'entry' and 'exit'\."):
+ validate_config_consistency(conf)
+
+
def test_load_config_test_comments() -> None:
"""
Load config with comments
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
index add6c586d..b51637143 100644
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -944,7 +944,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
trade.is_short = is_short
assert trade
assert trade.open_rate_requested == 10
- assert trade.isolated_liq == liq_price
+ assert trade.liquidation_price == liq_price
# In case of too high stake amount
diff --git a/tests/test_persistence.py b/tests/test_persistence.py
index c11987027..313f32685 100644
--- a/tests/test_persistence.py
+++ b/tests/test_persistence.py
@@ -116,38 +116,38 @@ def test_set_stop_loss_isolated_liq(fee):
trading_mode=margin
)
trade.set_isolated_liq(0.09)
- assert trade.isolated_liq == 0.09
+ assert trade.liquidation_price == 0.09
assert trade.stop_loss is None
assert trade.initial_stop_loss is None
trade._set_stop_loss(0.1, (1.0/9.0))
- assert trade.isolated_liq == 0.09
+ assert trade.liquidation_price == 0.09
assert trade.stop_loss == 0.1
assert trade.initial_stop_loss == 0.1
trade.set_isolated_liq(0.08)
- assert trade.isolated_liq == 0.08
+ assert trade.liquidation_price == 0.08
assert trade.stop_loss == 0.1
assert trade.initial_stop_loss == 0.1
trade.set_isolated_liq(0.11)
trade._set_stop_loss(0.1, 0)
- assert trade.isolated_liq == 0.11
+ assert trade.liquidation_price == 0.11
assert trade.stop_loss == 0.11
assert trade.initial_stop_loss == 0.1
# lower stop doesn't move stoploss
trade._set_stop_loss(0.1, 0)
- assert trade.isolated_liq == 0.11
+ assert trade.liquidation_price == 0.11
assert trade.stop_loss == 0.11
assert trade.initial_stop_loss == 0.1
trade.stop_loss = None
- trade.isolated_liq = None
+ trade.liquidation_price = None
trade.initial_stop_loss = None
trade._set_stop_loss(0.07, 0)
- assert trade.isolated_liq is None
+ assert trade.liquidation_price is None
assert trade.stop_loss == 0.07
assert trade.initial_stop_loss == 0.07
@@ -157,29 +157,29 @@ def test_set_stop_loss_isolated_liq(fee):
trade.initial_stop_loss = None
trade.set_isolated_liq(0.09)
- assert trade.isolated_liq == 0.09
+ assert trade.liquidation_price == 0.09
assert trade.stop_loss is None
assert trade.initial_stop_loss is None
trade._set_stop_loss(0.08, (1.0/9.0))
- assert trade.isolated_liq == 0.09
+ assert trade.liquidation_price == 0.09
assert trade.stop_loss == 0.08
assert trade.initial_stop_loss == 0.08
trade.set_isolated_liq(0.1)
- assert trade.isolated_liq == 0.1
+ assert trade.liquidation_price == 0.1
assert trade.stop_loss == 0.08
assert trade.initial_stop_loss == 0.08
trade.set_isolated_liq(0.07)
trade._set_stop_loss(0.1, (1.0/8.0))
- assert trade.isolated_liq == 0.07
+ assert trade.liquidation_price == 0.07
assert trade.stop_loss == 0.07
assert trade.initial_stop_loss == 0.08
# Stop doesn't move stop higher
trade._set_stop_loss(0.1, (1.0/9.0))
- assert trade.isolated_liq == 0.07
+ assert trade.liquidation_price == 0.07
assert trade.stop_loss == 0.07
assert trade.initial_stop_loss == 0.08
@@ -1474,7 +1474,7 @@ def test_adjust_stop_loss_short(fee):
trade.set_isolated_liq(0.63)
trade.adjust_stop_loss(0.59, -0.1)
assert trade.stop_loss == 0.63
- assert trade.isolated_liq == 0.63
+ assert trade.liquidation_price == 0.63
def test_adjust_min_max_rates(fee):
@@ -1539,7 +1539,7 @@ def test_get_open_lev(fee, use_db):
@pytest.mark.usefixtures("init_persistence")
-def test_to_json(default_conf, fee):
+def test_to_json(fee):
# Simulate dry_run entries
trade = Trade(
@@ -1608,7 +1608,7 @@ def test_to_json(default_conf, fee):
'exchange': 'binance',
'leverage': None,
'interest_rate': None,
- 'isolated_liq': None,
+ 'liquidation_price': None,
'is_short': None,
'trading_mode': None,
'funding_fees': None,
@@ -1683,7 +1683,7 @@ def test_to_json(default_conf, fee):
'exchange': 'binance',
'leverage': None,
'interest_rate': None,
- 'isolated_liq': None,
+ 'liquidation_price': None,
'is_short': None,
'trading_mode': None,
'funding_fees': None,