Merge pull request #9188 from Axel-CH/add-trade-param-to-custom-entry-price
Add trade param to custom entry price
This commit is contained in:
@@ -510,6 +510,9 @@ Each of these methods are called right before placing an order on the exchange.
|
|||||||
!!! Note
|
!!! Note
|
||||||
If your custom pricing function return None or an invalid value, price will fall back to `proposed_rate`, which is based on the regular pricing configuration.
|
If your custom pricing function return None or an invalid value, price will fall back to `proposed_rate`, which is based on the regular pricing configuration.
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
Using custom_entry_price, the Trade object will be available as soon as the first entry order associated with the trade is created, for the first entry, `trade` parameter value will be `None`.
|
||||||
|
|
||||||
### Custom order entry and exit price example
|
### Custom order entry and exit price example
|
||||||
|
|
||||||
``` python
|
``` python
|
||||||
@@ -520,7 +523,7 @@ class AwesomeStrategy(IStrategy):
|
|||||||
|
|
||||||
# ... populate_* methods
|
# ... populate_* methods
|
||||||
|
|
||||||
def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float,
|
def custom_entry_price(self, pair: str, trade: Optional['Trade'], current_time: datetime, proposed_rate: float,
|
||||||
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
||||||
|
|
||||||
dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair,
|
dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair,
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ After:
|
|||||||
|
|
||||||
``` python hl_lines="3"
|
``` python hl_lines="3"
|
||||||
class AwesomeStrategy(IStrategy):
|
class AwesomeStrategy(IStrategy):
|
||||||
def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float,
|
def custom_entry_price(self, pair: str, trade: Optional[Trade], current_time: datetime, proposed_rate: float,
|
||||||
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
||||||
return proposed_rate
|
return proposed_rate
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -938,7 +938,8 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
# Don't call custom_entry_price in order-adjust scenario
|
# Don't call custom_entry_price in order-adjust scenario
|
||||||
custom_entry_price = strategy_safe_wrapper(self.strategy.custom_entry_price,
|
custom_entry_price = strategy_safe_wrapper(self.strategy.custom_entry_price,
|
||||||
default_retval=enter_limit_requested)(
|
default_retval=enter_limit_requested)(
|
||||||
pair=pair, current_time=datetime.now(timezone.utc),
|
pair=pair, trade=trade,
|
||||||
|
current_time=datetime.now(timezone.utc),
|
||||||
proposed_rate=enter_limit_requested, entry_tag=entry_tag,
|
proposed_rate=enter_limit_requested, entry_tag=entry_tag,
|
||||||
side=trade_side,
|
side=trade_side,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -738,7 +738,9 @@ class Backtesting:
|
|||||||
if order_type == 'limit':
|
if order_type == 'limit':
|
||||||
new_rate = strategy_safe_wrapper(self.strategy.custom_entry_price,
|
new_rate = strategy_safe_wrapper(self.strategy.custom_entry_price,
|
||||||
default_retval=propose_rate)(
|
default_retval=propose_rate)(
|
||||||
pair=pair, current_time=current_time,
|
pair=pair,
|
||||||
|
trade=trade, # type: ignore[arg-type]
|
||||||
|
current_time=current_time,
|
||||||
proposed_rate=propose_rate, entry_tag=entry_tag,
|
proposed_rate=propose_rate, entry_tag=entry_tag,
|
||||||
side=direction,
|
side=direction,
|
||||||
) # default value is the open rate
|
) # default value is the open rate
|
||||||
|
|||||||
@@ -395,7 +395,8 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
"""
|
"""
|
||||||
return self.stoploss
|
return self.stoploss
|
||||||
|
|
||||||
def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float,
|
def custom_entry_price(self, pair: str, trade: Optional[Trade],
|
||||||
|
current_time: datetime, proposed_rate: float,
|
||||||
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
||||||
"""
|
"""
|
||||||
Custom entry price logic, returning the new entry price.
|
Custom entry price logic, returning the new entry price.
|
||||||
@@ -405,6 +406,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
When not implemented by a strategy, returns None, orderbook is used to set entry price
|
When not implemented by a strategy, returns None, orderbook is used to set entry price
|
||||||
|
|
||||||
:param pair: Pair that's currently analyzed
|
:param pair: Pair that's currently analyzed
|
||||||
|
:param trade: trade object (None for initial entries).
|
||||||
:param current_time: datetime object, containing the current datetime
|
:param current_time: datetime object, containing the current datetime
|
||||||
:param proposed_rate: Rate, calculated based on pricing settings in exit_pricing.
|
:param proposed_rate: Rate, calculated based on pricing settings in exit_pricing.
|
||||||
:param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
|
:param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ def bot_loop_start(self, current_time: datetime, **kwargs) -> None:
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def custom_entry_price(self, pair: str, current_time: 'datetime', proposed_rate: float,
|
def custom_entry_price(self, pair: str, trade: Optional['Trade'],
|
||||||
|
current_time: 'datetime', proposed_rate: float,
|
||||||
entry_tag: 'Optional[str]', side: str, **kwargs) -> float:
|
entry_tag: 'Optional[str]', side: str, **kwargs) -> float:
|
||||||
"""
|
"""
|
||||||
Custom entry price logic, returning the new entry price.
|
Custom entry price logic, returning the new entry price.
|
||||||
@@ -23,6 +24,7 @@ def custom_entry_price(self, pair: str, current_time: 'datetime', proposed_rate:
|
|||||||
When not implemented by a strategy, returns None, orderbook is used to set entry price
|
When not implemented by a strategy, returns None, orderbook is used to set entry price
|
||||||
|
|
||||||
:param pair: Pair that's currently analyzed
|
:param pair: Pair that's currently analyzed
|
||||||
|
:param trade: trade object (None for initial entries).
|
||||||
:param current_time: datetime object, containing the current datetime
|
:param current_time: datetime object, containing the current datetime
|
||||||
:param proposed_rate: Rate, calculated based on pricing settings in exit_pricing.
|
:param proposed_rate: Rate, calculated based on pricing settings in exit_pricing.
|
||||||
:param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
|
:param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ from typing import Optional
|
|||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
from strategy_test_v3 import StrategyTestV3
|
from strategy_test_v3 import StrategyTestV3
|
||||||
|
|
||||||
|
from freqtrade.persistence import Trade
|
||||||
|
|
||||||
|
|
||||||
class StrategyTestV3CustomEntryPrice(StrategyTestV3):
|
class StrategyTestV3CustomEntryPrice(StrategyTestV3):
|
||||||
"""
|
"""
|
||||||
@@ -31,7 +33,8 @@ class StrategyTestV3CustomEntryPrice(StrategyTestV3):
|
|||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float,
|
def custom_entry_price(self, pair: str, trade: Optional[Trade], current_time: datetime,
|
||||||
|
proposed_rate: float,
|
||||||
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
||||||
|
|
||||||
return self.new_entry_price
|
return self.new_entry_price
|
||||||
|
|||||||
Reference in New Issue
Block a user