diff --git a/freqtrade/main.py b/freqtrade/main.py index f96718c6b..ae8561c96 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -182,11 +182,12 @@ def create_trade(stake_amount: float) -> Optional[Trade]: else: return None + # Calculate amount and subtract fee + fee = exchange.get_fee() buy_limit = get_target_bid(exchange.get_ticker(pair)) - # TODO: apply fee to amount and also consider it for profit calculations - amount = stake_amount / buy_limit - order_id = exchange.buy(pair, buy_limit, amount) + amount = (1 - fee) * stake_amount / buy_limit + order_id = exchange.buy(pair, buy_limit, amount) # Create trade entity and return message = '*{}:* Buying [{}]({}) with limit `{:f}`'.format( exchange.get_name().upper(), @@ -196,9 +197,11 @@ def create_trade(stake_amount: float) -> Optional[Trade]: ) logger.info(message) telegram.send_msg(message) + # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL return Trade(pair=pair, stake_amount=stake_amount, amount=amount, + fee=fee * 2, open_rate=buy_limit, open_date=datetime.utcnow(), exchange=exchange.get_name().upper(), diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index d33f494e9..a30bf9bcf 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -54,10 +54,11 @@ class Trade(Base): exchange = Column(String, nullable=False) pair = Column(String, nullable=False) is_open = Column(Boolean, nullable=False, default=True) + fee = Column(Float, nullable=False, default=0.0) open_rate = Column(Float) close_rate = Column(Float) close_profit = Column(Float) - stake_amount = Column(Float, name='btc_amount', nullable=False) + stake_amount = Column(Float, nullable=False) amount = Column(Float) open_date = Column(DateTime, nullable=False, default=datetime.utcnow) close_date = Column(DateTime) @@ -95,14 +96,11 @@ class Trade(Base): self.open_order_id = None - # Flush changes - Trade.session.flush() - def calc_profit(self, rate: float=None) -> float: """ - Calculates the profit in percentage. + Calculates the profit in percentage (including fee). :param rate: rate to compare with (optional). If rate is not set self.close_rate will be used :return: profit in percentage as float """ - return (rate or self.close_rate - self.open_rate) / self.open_rate + return (rate or self.close_rate - self.open_rate) / self.open_rate - self.fee diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index c098c3dc0..cddf61f52 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -128,7 +128,7 @@ def test_handle_trade(conf, mocker): }) assert trade.close_rate == 0.17256061 - assert trade.close_profit == 1.3748724900565639 + assert trade.close_profit == 1.369872490056564 assert trade.close_date is not None diff --git a/freqtrade/tests/test_telegram.py b/freqtrade/tests/test_telegram.py index 109374321..7024aa282 100644 --- a/freqtrade/tests/test_telegram.py +++ b/freqtrade/tests/test_telegram.py @@ -152,8 +152,8 @@ def test_profit_handle(conf, update, mocker): _profit(bot=MagicBot(), update=update) assert msg_mock.call_count == 2 - assert '*ROI:* `1.582013 (10.55%)`' in msg_mock.call_args_list[-1][0][0] - assert 'Best Performing:* `BTC_ETH: 10.55%`' in msg_mock.call_args_list[-1][0][0] + assert '*ROI:* `1.507013 (10.05%)`' in msg_mock.call_args_list[-1][0][0] + assert 'Best Performing:* `BTC_ETH: 10.05%`' in msg_mock.call_args_list[-1][0][0] def test_forcesell_handle(conf, update, mocker): @@ -249,7 +249,7 @@ def test_performance_handle(conf, update, mocker): _performance(bot=MagicBot(), update=update) assert msg_mock.call_count == 2 assert 'Performance' in msg_mock.call_args_list[-1][0][0] - assert 'BTC_ETH\t10.55%' in msg_mock.call_args_list[-1][0][0] + assert 'BTC_ETH\t10.05%' in msg_mock.call_args_list[-1][0][0] def test_start_handle(conf, update, mocker):