updated logic

This commit is contained in:
Kavinkumar 2022-02-21 11:57:15 +05:30
parent d25f999901
commit fcddb09694
5 changed files with 75 additions and 49 deletions

View File

@ -478,7 +478,7 @@ class FreqtradeBot(LoggingMixin):
if stake_amount is not None and stake_amount < 0.0: if stake_amount is not None and stake_amount < 0.0:
# We should decrease our position # We should decrease our position
proposed_exit_rate = self.exchange.get_rate(pair, refresh=True, side="buy") proposed_exit_rate = self.exchange.get_rate(trade.pair, refresh=True, side="buy")
self.execute_trade_exit(trade, proposed_exit_rate, sell_reason=SellCheckTuple( self.execute_trade_exit(trade, proposed_exit_rate, sell_reason=SellCheckTuple(
sell_type=SellType.CUSTOM_SELL), sub_trade_amt=stake_amount) sell_type=SellType.CUSTOM_SELL), sub_trade_amt=stake_amount)
@ -710,7 +710,8 @@ class FreqtradeBot(LoggingMixin):
# Send the message # Send the message
self.rpc.send_msg(msg) self.rpc.send_msg(msg)
def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str, sub_trade: bool = False) -> None: def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str,
sub_trade: bool = False) -> None:
""" """
Sends rpc notification when a buy cancel occurred. Sends rpc notification when a buy cancel occurred.
""" """
@ -1231,12 +1232,14 @@ class FreqtradeBot(LoggingMixin):
self._notify_exit(trade, order_type, sub_trade=bool(sub_trade_amt)) self._notify_exit(trade, order_type, sub_trade=bool(sub_trade_amt))
# In case of market sell orders the order can be closed immediately # In case of market sell orders the order can be closed immediately
if order.get('status', 'unknown') in ('closed', 'expired'): if order.get('status', 'unknown') in ('closed', 'expired'):
self.update_trade_state(trade, trade.open_order_id, order, sub_trade=bool(sub_trade_amt)) self.update_trade_state(trade, trade.open_order_id, order,
sub_trade=bool(sub_trade_amt))
Trade.commit() Trade.commit()
return True return True
def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False, sub_trade: bool = False) -> None: def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False,
sub_trade: bool = False) -> None:
""" """
Sends rpc notification when a sell occurred. Sends rpc notification when a sell occurred.
""" """
@ -1271,7 +1274,6 @@ class FreqtradeBot(LoggingMixin):
'stake_currency': self.config['stake_currency'], 'stake_currency': self.config['stake_currency'],
'fiat_currency': self.config.get('fiat_display_currency', None), 'fiat_currency': self.config.get('fiat_display_currency', None),
'sub_trade': sub_trade, 'sub_trade': sub_trade,
'stake_amount': trade.stake_amount,
} }
if 'fiat_display_currency' in self.config: if 'fiat_display_currency' in self.config:
@ -1282,7 +1284,8 @@ class FreqtradeBot(LoggingMixin):
# Send the message # Send the message
self.rpc.send_msg(msg) self.rpc.send_msg(msg)
def _notify_exit_cancel(self, trade: Trade, order_type: str, reason: str, sub_trade: bool = False) -> None: def _notify_exit_cancel(self, trade: Trade, order_type: str, reason: str,
sub_trade: bool = False) -> None:
""" """
Sends rpc notification when a sell cancel occurred. Sends rpc notification when a sell cancel occurred.
""" """
@ -1334,7 +1337,8 @@ class FreqtradeBot(LoggingMixin):
# #
def update_trade_state(self, trade: Trade, order_id: str, action_order: Dict[str, Any] = None, def update_trade_state(self, trade: Trade, order_id: str, action_order: Dict[str, Any] = None,
stoploss_order: bool = False, send_msg: bool = True, sub_trade : bool = False) -> bool: stoploss_order: bool = False, send_msg: bool = True,
sub_trade: bool = False) -> bool:
""" """
Checks trades with open orders and updates the amount if necessary Checks trades with open orders and updates the amount if necessary
Handles closing both buy and sell orders. Handles closing both buy and sell orders.

View File

@ -116,7 +116,7 @@ class Order(_DECL_BASE):
ft_order_side = Column(String(25), nullable=False) ft_order_side = Column(String(25), nullable=False)
ft_pair = Column(String(25), nullable=False) ft_pair = Column(String(25), nullable=False)
ft_is_open = Column(Boolean, nullable=False, default=True, index=True) ft_is_open = Column(Boolean, nullable=False, default=True, index=True)
is_processed = Column(Boolean, nullable=True, default=False) is_realized = Column(Boolean, nullable=True, default=False)
order_id = Column(String(255), nullable=False, index=True) order_id = Column(String(255), nullable=False, index=True)
status = Column(String(255), nullable=True) status = Column(String(255), nullable=True)
@ -479,22 +479,8 @@ class LocalTrade():
logger.info(f'{order_type.upper()}_SELL has been fulfilled for {self}.') logger.info(f'{order_type.upper()}_SELL has been fulfilled for {self}.')
self.open_order_id = None self.open_order_id = None
if sub_trade: if sub_trade:
orders=(self.select_filled_orders('buy')) self.process_sell_sub_trade(order)
lbuy=orders[-2] return
lamount = (lbuy.filled or lbuy.amount)
o_rate = float(safe_value_fallback(order, 'average', 'price'))
o_amount = float(safe_value_fallback(order, 'filled', 'amount'))
o1_rate = orders[-1].average or orders[-1].price
lbuy.average=(lbuy.average * lamount - self.calc_profit2(o1_rate, o_rate, o_amount))/lamount
orders[-1].is_processed=True
self.update_order(orders[-1])
# self.orders.remove(orders[-1])
self.update_order(lbuy)
Order.query.session.commit()
self.recalc_trade_from_orders()
Trade.commit()
else: else:
self.close(safe_value_fallback(order, 'average', 'price')) self.close(safe_value_fallback(order, 'average', 'price'))
elif order_type in ('stop_loss_limit', 'stop-loss', 'stop-loss-limit', 'stop'): elif order_type in ('stop_loss_limit', 'stop-loss', 'stop-loss-limit', 'stop'):
@ -508,9 +494,43 @@ class LocalTrade():
raise ValueError(f'Unknown order type: {order_type}') raise ValueError(f'Unknown order type: {order_type}')
Trade.commit() Trade.commit()
def calc_profit2(self, open_rate: float, close_rate: float, amount: float) ->float: def process_sell_sub_trade(self, order: Dict) -> None:
return float (Decimal(amount) * \ orders = (self.select_filled_orders('buy'))
( Decimal(1-self.fee_close)* Decimal(close_rate) - \ sell_rate = float(safe_value_fallback(order, 'average', 'price'))
sell_amount = float(safe_value_fallback(order, 'filled', 'amount'))
profit = 0
idx = -1
while sell_amount:
border = orders[idx]
buy_amount = border.filled or border.amount
buy_rate = border.average or border.price
if sell_amount < buy_amount:
amount = sell_amount
else:
if len(orders) == 1 and sell_amount == buy_amount:
self.close(safe_value_fallback(order, 'average', 'price'))
Trade.commit()
return
border.is_realized = True
self.update_order(border)
idx -= 1
amount = buy_amount
sell_amount -= amount
profit += self.calc_profit2(buy_rate, sell_rate, amount)
border2 = orders[idx]
if not border.is_realized:
border2.filled -= amount
amount2 = border2.filled or border2.amount
border2.average = (border2.average * amount2 - profit) / amount2
self.update_order(border2)
Order.query.session.commit()
self.recalc_trade_from_orders()
Trade.commit()
def calc_profit2(self, open_rate: float, close_rate: float,
amount: float) -> float:
return float(Decimal(amount) *
(Decimal(1 - self.fee_close) * Decimal(close_rate) -
Decimal(1 + self.fee_open) * Decimal(open_rate))) Decimal(1 + self.fee_open) * Decimal(open_rate)))
def close(self, rate: float, *, show_msg: bool = True) -> None: def close(self, rate: float, *, show_msg: bool = True) -> None:
@ -650,7 +670,7 @@ class LocalTrade():
for o in self.orders: for o in self.orders:
if (o.ft_is_open or if (o.ft_is_open or
(o.ft_order_side != 'buy') or (o.ft_order_side != 'buy') or
o.is_processed==True or o.is_realized or
(o.status not in NON_OPEN_EXCHANGE_STATES)): (o.status not in NON_OPEN_EXCHANGE_STATES)):
continue continue
@ -708,7 +728,7 @@ class LocalTrade():
return [o for o in self.orders if ((o.ft_order_side == order_side) or (order_side is None)) return [o for o in self.orders if ((o.ft_order_side == order_side) or (order_side is None))
and o.ft_is_open is False and and o.ft_is_open is False and
(o.filled or 0) > 0 and (o.filled or 0) > 0 and
o.is_processed!=True and not o.is_realized and
o.status in NON_OPEN_EXCHANGE_STATES] o.status in NON_OPEN_EXCHANGE_STATES]
@property @property

View File

@ -253,7 +253,8 @@ class Telegram(RPCHandler):
message += ")`" message += ")`"
if msg.get('sub_trade'): if msg.get('sub_trade'):
message += f"\n*Balance:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}" bal = round_coin_value(msg['stake_amount'], msg['stake_currency'])
message += f"\n*Balance:* `({bal}"
if msg.get('fiat_currency', None): if msg.get('fiat_currency', None):
message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}"
@ -306,7 +307,8 @@ class Telegram(RPCHandler):
msg['stake_amount'], msg['stake_currency'], msg['fiat_currency']) msg['stake_amount'], msg['stake_currency'], msg['fiat_currency'])
else: else:
msg['stake_amount_fiat'] = 0 msg['stake_amount_fiat'] = 0
message += f"\n*Balance:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}" bal = round_coin_value(msg['stake_amount'], msg['stake_currency'])
message += f"\n*Balance:* `({bal}"
if msg.get('fiat_currency', None): if msg.get('fiat_currency', None):
message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}"

View File

@ -2621,7 +2621,6 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_
'close_rate': ANY, 'close_rate': ANY,
'sub_trade': False, 'sub_trade': False,
'stake_amount': 60.0, 'stake_amount': 60.0,
} == last_msg } == last_msg
@ -4553,11 +4552,11 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=closed_sell_dca_order_1)) MagicMock(return_value=closed_sell_dca_order_1))
assert freqtrade.execute_trade_exit(trade=trade, limit=8, assert freqtrade.execute_trade_exit(trade=trade, limit=8,
sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS),sub_trade_amt=15) sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS),
sub_trade_amt=15)
# Assert trade is as expected (averaged dca) # Assert trade is as expected (averaged dca)
trade = Trade.query.first() trade = Trade.query.first()
print(trade.open_rate,trade.amount,trade.stake_amount,'DEBUG')
assert trade assert trade
assert trade.open_order_id is None assert trade.open_order_id is None
assert trade.amount == 22 assert trade.amount == 22
@ -4572,6 +4571,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
order = trade.select_order('sell', False) order = trade.select_order('sell', False)
assert order.order_id == '653' assert order.order_id == '653'
def test_process_open_trade_positions_exception(mocker, default_conf_usdt, fee, caplog) -> None: def test_process_open_trade_positions_exception(mocker, default_conf_usdt, fee, caplog) -> None:
default_conf_usdt.update({ default_conf_usdt.update({
"position_adjustment_enable": True, "position_adjustment_enable": True,