Skip to content

Commit

Permalink
Implement strategy-controlled stake sizes.
Browse files Browse the repository at this point in the history
  • Loading branch information
rokups committed Jul 3, 2021
1 parent e9dbd57 commit 899515c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
25 changes: 18 additions & 7 deletions freqtrade/freqtradebot.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,16 +424,10 @@ def create_trade(self, pair: str) -> bool:

if buy and not sell:
stake_amount = self.wallets.get_trade_stake_amount(pair, self.edge)
if not stake_amount:
logger.debug(f"Stake amount is 0, ignoring possible trade for {pair}.")
return False

logger.info(f"Buy signal found: about create a new trade for {pair} with stake_amount: "
f"{stake_amount} ...")

bid_check_dom = self.config.get('bid_strategy', {}).get('check_depth_of_market', {})
if ((bid_check_dom.get('enabled', False)) and
(bid_check_dom.get('bids_to_ask_delta', 0) > 0)):
(bid_check_dom.get('bids_to_ask_delta', 0) > 0)):
if self._check_depth_of_market_buy(pair, bid_check_dom):
return self.execute_buy(pair, stake_amount)
else:
Expand Down Expand Up @@ -488,13 +482,30 @@ def execute_buy(self, pair: str, stake_amount: float, price: Optional[float] = N

min_stake_amount = self.exchange.get_min_pair_stake_amount(pair, buy_limit_requested,
self.strategy.stoploss)

if not self.edge:
max_stake_amount = self.wallets._get_available_stake_amount(
Trade.total_open_trades_stakes())
stake_amount = strategy_safe_wrapper(self.strategy.custom_stake_amount,
default_retval=None)(
pair=pair, current_time=datetime.now(timezone.utc),
current_rate=buy_limit_requested, proposed_stake=stake_amount,
min_stake=min_stake_amount, max_stake=max_stake_amount)

if not stake_amount or stake_amount > max_stake_amount:
logger.debug(f"Stake amount is {stake_amount}, ignoring possible trade for {pair}.")
return False

if min_stake_amount is not None and min_stake_amount > stake_amount:
logger.warning(
f"Can't open a new trade for {pair}: stake amount "
f"is too small ({stake_amount} < {min_stake_amount})"
)
return False

logger.info(f"Buy signal found: about create a new trade for {pair} with stake_amount: "
f"{stake_amount} ...")

amount = stake_amount / buy_limit_requested
order_type = self.strategy.order_types['buy']
if forcebuy:
Expand Down
15 changes: 14 additions & 1 deletion freqtrade/optimize/backtesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,20 @@ def _enter_trade(self, pair: str, row: List) -> Optional[LocalTrade]:
stake_amount = self.wallets.get_trade_stake_amount(pair, None)
except DependencyException:
return None
min_stake_amount = self.exchange.get_min_pair_stake_amount(pair, row[OPEN_IDX], -0.05)

min_stake_amount = self.exchange.get_min_pair_stake_amount(pair, row[OPEN_IDX], -0.05) or 0
max_stake_amount = self.wallets._get_available_stake_amount(
Trade.total_open_trades_stakes())

stake_amount = strategy_safe_wrapper(self.strategy.custom_stake_amount,
default_retval=None)(
pair=pair, current_time=row[DATE_IDX].to_pydatetime(), current_rate=row[OPEN_IDX],
proposed_stake=stake_amount, min_stake=min_stake_amount, max_stake=max_stake_amount)
if not stake_amount or stake_amount < min_stake_amount or \
(stake_amount or 0) > max_stake_amount:
logger.error(f'Strategy requested stake amount to be {stake_amount}, while stake '
f'amount must be between {min_stake_amount} and {max_stake_amount}.')
return None

order_type = self.strategy.order_types['buy']
time_in_force = self.strategy.order_time_in_force['sell']
Expand Down
17 changes: 17 additions & 0 deletions freqtrade/strategy/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,23 @@ def custom_sell(self, pair: str, trade: Trade, current_time: datetime, current_r
"""
return None

def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
"""
Customize stake size 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_stake: A stake amount proposed by the bot.
:param min_stake: Minimal stake size allowed by exchange.
:param max_stake: Balance available for trading.
:return: A stake size, which is between min_stake and max_stake.
"""
return proposed_stake

def informative_pairs(self) -> ListPairsWithTimeframes:
"""
Define additional, informative pair/interval combinations to be cached from the exchange.
Expand Down

0 comments on commit 899515c

Please sign in to comment.