add fee to sqlalchemy model and respecting it in calc_profit
This commit is contained in:
parent
41510fdb32
commit
cd18629433
@ -182,11 +182,12 @@ def create_trade(stake_amount: float) -> Optional[Trade]:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Calculate amount and subtract fee
|
||||||
|
fee = exchange.get_fee()
|
||||||
buy_limit = get_target_bid(exchange.get_ticker(pair))
|
buy_limit = get_target_bid(exchange.get_ticker(pair))
|
||||||
# TODO: apply fee to amount and also consider it for profit calculations
|
amount = (1 - fee) * stake_amount / buy_limit
|
||||||
amount = stake_amount / buy_limit
|
|
||||||
order_id = exchange.buy(pair, buy_limit, amount)
|
|
||||||
|
|
||||||
|
order_id = exchange.buy(pair, buy_limit, amount)
|
||||||
# Create trade entity and return
|
# Create trade entity and return
|
||||||
message = '*{}:* Buying [{}]({}) with limit `{:f}`'.format(
|
message = '*{}:* Buying [{}]({}) with limit `{:f}`'.format(
|
||||||
exchange.get_name().upper(),
|
exchange.get_name().upper(),
|
||||||
@ -196,9 +197,11 @@ def create_trade(stake_amount: float) -> Optional[Trade]:
|
|||||||
)
|
)
|
||||||
logger.info(message)
|
logger.info(message)
|
||||||
telegram.send_msg(message)
|
telegram.send_msg(message)
|
||||||
|
# Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
|
||||||
return Trade(pair=pair,
|
return Trade(pair=pair,
|
||||||
stake_amount=stake_amount,
|
stake_amount=stake_amount,
|
||||||
amount=amount,
|
amount=amount,
|
||||||
|
fee=fee * 2,
|
||||||
open_rate=buy_limit,
|
open_rate=buy_limit,
|
||||||
open_date=datetime.utcnow(),
|
open_date=datetime.utcnow(),
|
||||||
exchange=exchange.get_name().upper(),
|
exchange=exchange.get_name().upper(),
|
||||||
|
@ -54,10 +54,11 @@ class Trade(Base):
|
|||||||
exchange = Column(String, nullable=False)
|
exchange = Column(String, nullable=False)
|
||||||
pair = Column(String, nullable=False)
|
pair = Column(String, nullable=False)
|
||||||
is_open = Column(Boolean, nullable=False, default=True)
|
is_open = Column(Boolean, nullable=False, default=True)
|
||||||
|
fee = Column(Float, nullable=False, default=0.0)
|
||||||
open_rate = Column(Float)
|
open_rate = Column(Float)
|
||||||
close_rate = Column(Float)
|
close_rate = Column(Float)
|
||||||
close_profit = Column(Float)
|
close_profit = Column(Float)
|
||||||
stake_amount = Column(Float, name='btc_amount', nullable=False)
|
stake_amount = Column(Float, nullable=False)
|
||||||
amount = Column(Float)
|
amount = Column(Float)
|
||||||
open_date = Column(DateTime, nullable=False, default=datetime.utcnow)
|
open_date = Column(DateTime, nullable=False, default=datetime.utcnow)
|
||||||
close_date = Column(DateTime)
|
close_date = Column(DateTime)
|
||||||
@ -95,14 +96,11 @@ class Trade(Base):
|
|||||||
|
|
||||||
self.open_order_id = None
|
self.open_order_id = None
|
||||||
|
|
||||||
# Flush changes
|
|
||||||
Trade.session.flush()
|
|
||||||
|
|
||||||
def calc_profit(self, rate: float=None) -> float:
|
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).
|
:param rate: rate to compare with (optional).
|
||||||
If rate is not set self.close_rate will be used
|
If rate is not set self.close_rate will be used
|
||||||
:return: profit in percentage as float
|
: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
|
||||||
|
@ -128,7 +128,7 @@ def test_handle_trade(conf, mocker):
|
|||||||
})
|
})
|
||||||
|
|
||||||
assert trade.close_rate == 0.17256061
|
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
|
assert trade.close_date is not None
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,8 +152,8 @@ def test_profit_handle(conf, update, mocker):
|
|||||||
|
|
||||||
_profit(bot=MagicBot(), update=update)
|
_profit(bot=MagicBot(), update=update)
|
||||||
assert msg_mock.call_count == 2
|
assert msg_mock.call_count == 2
|
||||||
assert '*ROI:* `1.582013 (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.55%`' 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):
|
def test_forcesell_handle(conf, update, mocker):
|
||||||
@ -249,7 +249,7 @@ def test_performance_handle(conf, update, mocker):
|
|||||||
_performance(bot=MagicBot(), update=update)
|
_performance(bot=MagicBot(), update=update)
|
||||||
assert msg_mock.call_count == 2
|
assert msg_mock.call_count == 2
|
||||||
assert 'Performance' in msg_mock.call_args_list[-1][0][0]
|
assert 'Performance' in msg_mock.call_args_list[-1][0][0]
|
||||||
assert '<code>BTC_ETH\t10.55%</code>' in msg_mock.call_args_list[-1][0][0]
|
assert '<code>BTC_ETH\t10.05%</code>' in msg_mock.call_args_list[-1][0][0]
|
||||||
|
|
||||||
|
|
||||||
def test_start_handle(conf, update, mocker):
|
def test_start_handle(conf, update, mocker):
|
||||||
|
Loading…
Reference in New Issue
Block a user