diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index e3ef01dd5..8efc6ab59 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -159,6 +159,8 @@ class FreqtradeBot(LoggingMixin): performs startup tasks """ self.rpc.startup_messages(self.config, self.pairlists, self.protections) + # Update older trades with precision and precision mode + self.startup_backpopulate_precision() if not self.edge: # Adjust stoploss if it was changed Trade.stoploss_reinitialization(self.strategy.stoploss) @@ -286,6 +288,15 @@ class FreqtradeBot(LoggingMixin): else: return 0.0 + def startup_backpopulate_precision(self): + + trades = Trade.get_trades([Trade.precision_mode.is_(None)]) + for trade in trades: + trade.precision_mode = self.exchange.precisionMode + trade.amount_precision = self.exchange.get_precision_amount(trade.pair) + trade.price_precision = self.exchange.get_precision_price(trade.pair) + Trade.commit() + def startup_update_open_orders(self): """ Updates open orders based on order list kept in the database. @@ -738,7 +749,10 @@ class FreqtradeBot(LoggingMixin): leverage=leverage, is_short=is_short, trading_mode=self.trading_mode, - funding_fees=funding_fees + funding_fees=funding_fees, + amount_precision=self.exchange.get_precision_amount(pair), + price_precision=self.exchange.get_precision_price(pair), + precision_mode=self.exchange.precisionMode, ) else: # This is additional buy, we reset fee_open_currency so timeout checking can work diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 029946cfb..795d20644 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -837,6 +837,9 @@ class Backtesting: trading_mode=self.trading_mode, leverage=leverage, # interest_rate=interest_rate, + amount_precision=self.exchange.get_precision_amount(pair), + price_precision=self.exchange.get_precision_price(pair), + precision_mode=self.exchange.precisionMode, orders=[], ) diff --git a/freqtrade/persistence/migrations.py b/freqtrade/persistence/migrations.py index 81757a7de..e54675f16 100644 --- a/freqtrade/persistence/migrations.py +++ b/freqtrade/persistence/migrations.py @@ -130,6 +130,10 @@ def migrate_trades_and_orders_table( get_column_def(cols, 'sell_order_status', 'null')) amount_requested = get_column_def(cols, 'amount_requested', 'amount') + amount_precision = get_column_def(cols, 'amount_precision', 'null') + price_precision = get_column_def(cols, 'price_precision', 'null') + precision_mode = get_column_def(cols, 'precision_mode', 'null') + # Schema migration necessary with engine.begin() as connection: connection.execute(text(f"alter table trades rename to {trade_back_name}")) @@ -156,7 +160,8 @@ def migrate_trades_and_orders_table( max_rate, min_rate, exit_reason, exit_order_status, strategy, enter_tag, timeframe, open_trade_value, close_profit_abs, trading_mode, leverage, liquidation_price, is_short, - interest_rate, funding_fees, realized_profit + interest_rate, funding_fees, realized_profit, + amount_precision, price_precision, precision_mode ) select id, lower(exchange), pair, {base_currency} base_currency, {stake_currency} stake_currency, @@ -182,7 +187,9 @@ def migrate_trades_and_orders_table( {open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs, {trading_mode} trading_mode, {leverage} leverage, {liquidation_price} liquidation_price, {is_short} is_short, {interest_rate} interest_rate, - {funding_fees} funding_fees, {realized_profit} realized_profit + {funding_fees} funding_fees, {realized_profit} realized_profit, + {amount_precision} amount_precision, {price_precision} price_precision, + {precision_mode} precision_mode from {trade_back_name} """)) @@ -300,7 +307,7 @@ def check_migrate(engine, decl_base, previous_tables) -> None: # Migrates both trades and orders table! # if ('orders' not in previous_tables # or not has_column(cols_orders, 'stop_price')): - if not has_column(cols_trades, 'realized_profit'): + if not has_column(cols_trades, 'precision_mode'): 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/trade_model.py b/freqtrade/persistence/trade_model.py index 864b4fde9..436919bb1 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -14,6 +14,7 @@ from freqtrade.constants import (DATETIME_PRINT_FORMAT, MATH_CLOSE_PREC, NON_OPE BuySell, LongShort) from freqtrade.enums import ExitType, TradingMode from freqtrade.exceptions import DependencyException, OperationalException +from freqtrade.exchange import amount_to_precision, price_to_precision from freqtrade.leverage import interest from freqtrade.persistence.base import _DECL_BASE from freqtrade.util import FtPrecise @@ -292,6 +293,9 @@ class LocalTrade(): timeframe: Optional[int] = None trading_mode: TradingMode = TradingMode.SPOT + amount_precision: Optional[float] = None + price_precision: Optional[float] = None + precision_mode: Optional[int] = None # Leverage trading properties liquidation_price: Optional[float] = None @@ -874,9 +878,11 @@ class LocalTrade(): if current_amount > ZERO: # Trade is still open # Leverage not updated, as we don't allow changing leverage through DCA at the moment. - self.open_rate = float(current_stake / current_amount) + self.open_rate = price_to_precision(float(current_stake / current_amount), + self.price_precision, self.precision_mode) + self.amount = amount_to_precision(float(current_amount), + self.amount_precision, self.precision_mode) self.stake_amount = float(current_stake) / (self.leverage or 1.0) - self.amount = float(current_amount) self.fee_open_cost = self.fee_open * float(current_stake) self.recalc_open_trade_value() if self.stop_loss_pct is not None and self.open_rate is not None: @@ -1120,6 +1126,9 @@ class Trade(_DECL_BASE, LocalTrade): timeframe = Column(Integer, nullable=True) trading_mode = Column(Enum(TradingMode), nullable=True) + amount_precision = Column(Float) + price_precision = Column(Float) + precision_mode = Column(Integer) # Leverage trading properties leverage = Column(Float, nullable=True, default=1.0)