Test and document leverage strategy callback
This commit is contained in:
parent
c791b95405
commit
5928ba9c88
@ -642,6 +642,34 @@ Freqtrade will fall back to the `proposed_stake` value should your code raise an
|
|||||||
!!! Tip
|
!!! Tip
|
||||||
Returning `0` or `None` will prevent trades from being placed.
|
Returning `0` or `None` will prevent trades from being placed.
|
||||||
|
|
||||||
|
## Leverage Callback
|
||||||
|
|
||||||
|
When trading in markets that allow leverage, this method must return the desired Leverage (Defaults to 1 -> No leverage).
|
||||||
|
|
||||||
|
Assuming a capital of 500USDT, a trade with leverage=3 would result in a position with 500 x 3 = 1500 USDT.
|
||||||
|
|
||||||
|
Values that are above `max_leverage` will be adjusted to `max_leverage`.
|
||||||
|
For markets / exchanges that don't support leverage, this method is ignored.
|
||||||
|
|
||||||
|
``` python
|
||||||
|
class AwesomeStrategy(IStrategy):
|
||||||
|
def leverage(self, pair: str, current_time: 'datetime', current_rate: float,
|
||||||
|
proposed_leverage: float, max_leverage: float, side: str,
|
||||||
|
**kwargs) -> float:
|
||||||
|
"""
|
||||||
|
Customize leverage for each new trade.
|
||||||
|
|
||||||
|
:param pair: Pair that's currently analyzed
|
||||||
|
:param current_time: datetime object, containing the current datetime
|
||||||
|
:param current_rate: Rate, calculated based on pricing settings in ask_strategy.
|
||||||
|
:param proposed_leverage: A leverage proposed by the bot.
|
||||||
|
:param max_leverage: Max leverage allowed on this pair
|
||||||
|
:param side: 'long' or 'short' - indicating the direction of the proposed trade
|
||||||
|
:return: A leverage amount, which is between 1.0 and max_leverage.
|
||||||
|
"""
|
||||||
|
return 1.0
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Derived strategies
|
## Derived strategies
|
||||||
|
@ -370,8 +370,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
proposed_stake: float, min_stake: float, max_stake: float,
|
||||||
**kwargs) -> float:
|
**kwargs) -> float:
|
||||||
"""
|
"""
|
||||||
Customize stake size for each new trade. This method is not called when edge module is
|
Customize stake size for each new trade.
|
||||||
enabled.
|
|
||||||
|
|
||||||
:param pair: Pair that's currently analyzed
|
:param pair: Pair that's currently analyzed
|
||||||
:param current_time: datetime object, containing the current datetime
|
:param current_time: datetime object, containing the current datetime
|
||||||
@ -383,6 +382,23 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
"""
|
"""
|
||||||
return proposed_stake
|
return proposed_stake
|
||||||
|
|
||||||
|
def leverage(self, pair: str, current_time: datetime, current_rate: float,
|
||||||
|
proposed_leverage: float, max_leverage: float, side: str,
|
||||||
|
**kwargs) -> float:
|
||||||
|
"""
|
||||||
|
Customize leverage for each new trade. This method is not called when edge module is
|
||||||
|
enabled.
|
||||||
|
|
||||||
|
:param pair: Pair that's currently analyzed
|
||||||
|
:param current_time: datetime object, containing the current datetime
|
||||||
|
:param current_rate: Rate, calculated based on pricing settings in ask_strategy.
|
||||||
|
:param proposed_leverage: A leverage proposed by the bot.
|
||||||
|
:param max_leverage: Max leverage allowed on this pair
|
||||||
|
:param side: 'long' or 'short' - indicating the direction of the proposed trade
|
||||||
|
:return: A leverage amount, which is between 1.0 and max_leverage.
|
||||||
|
"""
|
||||||
|
return 1.0
|
||||||
|
|
||||||
def informative_pairs(self) -> ListPairsWithTimeframes:
|
def informative_pairs(self) -> ListPairsWithTimeframes:
|
||||||
"""
|
"""
|
||||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
Define additional, informative pair/interval combinations to be cached from the exchange.
|
||||||
@ -971,20 +987,3 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
if 'exit_long' not in df.columns:
|
if 'exit_long' not in df.columns:
|
||||||
df = df.rename({'sell': 'exit_long'}, axis='columns')
|
df = df.rename({'sell': 'exit_long'}, axis='columns')
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def leverage(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_leverage: float, max_leverage: float, side: str,
|
|
||||||
**kwargs) -> float:
|
|
||||||
"""
|
|
||||||
Customize leverage for each new trade. This method is not called when edge module is
|
|
||||||
enabled.
|
|
||||||
|
|
||||||
:param pair: Pair that's currently analyzed
|
|
||||||
:param current_time: datetime object, containing the current datetime
|
|
||||||
:param current_rate: Rate, calculated based on pricing settings in ask_strategy.
|
|
||||||
:param proposed_leverage: A leverage proposed by the bot.
|
|
||||||
:param max_leverage: Max leverage allowed on this pair
|
|
||||||
:param side: 'long' or 'short' - indicating the direction of the proposed trade
|
|
||||||
:return: A leverage amount, which is between 1.0 and max_leverage.
|
|
||||||
"""
|
|
||||||
return 1.0
|
|
||||||
|
@ -36,6 +36,7 @@ logging.getLogger('').setLevel(logging.INFO)
|
|||||||
np.seterr(all='raise')
|
np.seterr(all='raise')
|
||||||
|
|
||||||
CURRENT_TEST_STRATEGY = 'StrategyTestV3'
|
CURRENT_TEST_STRATEGY = 'StrategyTestV3'
|
||||||
|
TRADE_SIDES = ('long', 'short')
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
import talib.abstract as ta
|
import talib.abstract as ta
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
@ -159,3 +160,11 @@ class StrategyTestV3(IStrategy):
|
|||||||
|
|
||||||
# TODO-lev: Add short logic
|
# TODO-lev: Add short logic
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
def leverage(self, pair: str, current_time: datetime, current_rate: float,
|
||||||
|
proposed_leverage: float, max_leverage: float, side: str,
|
||||||
|
**kwargs) -> float:
|
||||||
|
# Return 3.0 in all cases.
|
||||||
|
# Bot-logic must make sure it's an allowed leverage and eventually adjust accordingly.
|
||||||
|
|
||||||
|
return 3.0
|
||||||
|
@ -21,7 +21,7 @@ from freqtrade.strategy.hyper import (BaseParameter, BooleanParameter, Categoric
|
|||||||
DecimalParameter, IntParameter, RealParameter)
|
DecimalParameter, IntParameter, RealParameter)
|
||||||
from freqtrade.strategy.interface import SellCheckTuple
|
from freqtrade.strategy.interface import SellCheckTuple
|
||||||
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
||||||
from tests.conftest import log_has, log_has_re
|
from tests.conftest import CURRENT_TEST_STRATEGY, TRADE_SIDES, log_has, log_has_re
|
||||||
|
|
||||||
from .strats.strategy_test_v3 import StrategyTestV3
|
from .strats.strategy_test_v3 import StrategyTestV3
|
||||||
|
|
||||||
@ -506,6 +506,32 @@ def test_custom_sell(default_conf, fee, caplog) -> None:
|
|||||||
assert log_has_re('Custom sell reason returned from custom_sell is too long.*', caplog)
|
assert log_has_re('Custom sell reason returned from custom_sell is too long.*', caplog)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('side', TRADE_SIDES)
|
||||||
|
def test_leverage_callback(default_conf, side) -> None:
|
||||||
|
default_conf['strategy'] = 'StrategyTestV2'
|
||||||
|
strategy = StrategyResolver.load_strategy(default_conf)
|
||||||
|
|
||||||
|
assert strategy.leverage(
|
||||||
|
pair='XRP/USDT',
|
||||||
|
current_time=datetime.now(timezone.utc),
|
||||||
|
current_rate=2.2,
|
||||||
|
proposed_leverage=1.0,
|
||||||
|
max_leverage=5.0,
|
||||||
|
side=side,
|
||||||
|
) == 1
|
||||||
|
|
||||||
|
default_conf['strategy'] = CURRENT_TEST_STRATEGY
|
||||||
|
strategy = StrategyResolver.load_strategy(default_conf)
|
||||||
|
assert strategy.leverage(
|
||||||
|
pair='XRP/USDT',
|
||||||
|
current_time=datetime.now(timezone.utc),
|
||||||
|
current_rate=2.2,
|
||||||
|
proposed_leverage=1.0,
|
||||||
|
max_leverage=5.0,
|
||||||
|
side=side,
|
||||||
|
) == 3
|
||||||
|
|
||||||
|
|
||||||
def test_analyze_ticker_default(ohlcv_history, mocker, caplog) -> None:
|
def test_analyze_ticker_default(ohlcv_history, mocker, caplog) -> None:
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
ind_mock = MagicMock(side_effect=lambda x, meta: x)
|
ind_mock = MagicMock(side_effect=lambda x, meta: x)
|
||||||
|
Loading…
Reference in New Issue
Block a user