included unit test

This commit is contained in:
Kavinkumar 2022-02-19 18:55:07 +05:30
parent da48ac9dab
commit 250664d8b3
5 changed files with 91 additions and 30 deletions

View File

@ -480,7 +480,7 @@ class FreqtradeBot(LoggingMixin):
# We should decrease our position
proposed_exit_rate = self.exchange.get_rate(pair, refresh=True, side="buy")
self.execute_trade_exit(trade, proposed_exit_rate, sell_reason=SellCheckTuple(
sell_type=SellType.CUSTOM_SELL), partial=stake_amount)
sell_type=SellType.CUSTOM_SELL), sub_trade_amt=stake_amount)
def _check_depth_of_market_buy(self, pair: str, conf: Dict) -> bool:
"""
@ -620,7 +620,7 @@ class FreqtradeBot(LoggingMixin):
# Updating wallets
self.wallets.update()
self._notify_enter(trade, order, order_type, partial=pos_adjust)
self._notify_enter(trade, order, order_type, sub_trade=pos_adjust)
if pos_adjust:
if order_status == 'closed':
@ -677,7 +677,7 @@ class FreqtradeBot(LoggingMixin):
return enter_limit_requested, stake_amount
def _notify_enter(self, trade: Trade, order: Dict, order_type: Optional[str] = None,
fill: bool = False, partial: bool = False) -> None:
fill: bool = False, sub_trade: bool = False) -> None:
"""
Sends rpc notification when a buy occurred.
"""
@ -704,13 +704,13 @@ class FreqtradeBot(LoggingMixin):
'amount': safe_value_fallback(order, 'filled', 'amount') or trade.amount,
'open_date': trade.open_date or datetime.utcnow(),
'current_rate': current_rate,
'partial': partial,
'sub_trade': sub_trade,
}
# Send the message
self.rpc.send_msg(msg)
def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str) -> 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.
"""
@ -731,6 +731,7 @@ class FreqtradeBot(LoggingMixin):
'open_date': trade.open_date,
'current_rate': current_rate,
'reason': reason,
'sub_trade': sub_trade,
}
# Send the message
@ -1154,7 +1155,7 @@ class FreqtradeBot(LoggingMixin):
*,
exit_tag: Optional[str] = None,
ordertype: Optional[str] = None,
partial: float = None,
sub_trade_amt: float = None,
) -> bool:
"""
Executes a trade exit for the given trade and limit
@ -1192,7 +1193,7 @@ class FreqtradeBot(LoggingMixin):
# Emergency sells (default to market!)
order_type = self.strategy.order_types.get("emergencysell", "market")
amount = self._safe_exit_amount(trade.pair, trade.amount)
amount = sub_trade_amt or self._safe_exit_amount(trade.pair, trade.amount)
time_in_force = self.strategy.order_time_in_force['sell']
if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)(
@ -1227,15 +1228,15 @@ class FreqtradeBot(LoggingMixin):
self.strategy.lock_pair(trade.pair, datetime.now(timezone.utc),
reason='Auto lock')
self._notify_exit(trade, order_type, partial=bool(partial))
self._notify_exit(trade, order_type, sub_trade=bool(sub_trade_amt))
# In case of market sell orders the order can be closed immediately
if order.get('status', 'unknown') in ('closed', 'expired'):
self.update_trade_state(trade, trade.open_order_id, order)
self.update_trade_state(trade, trade.open_order_id, order, sub_trade=bool(sub_trade_amt))
Trade.commit()
return True
def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False, partial: 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.
"""
@ -1269,7 +1270,8 @@ class FreqtradeBot(LoggingMixin):
'stake_amount': trade.stake_amount,
'stake_currency': self.config['stake_currency'],
'fiat_currency': self.config.get('fiat_display_currency', None),
'partial': partial,
'sub_trade': sub_trade,
'stake_amount': trade.stake_amount,
}
if 'fiat_display_currency' in self.config:
@ -1280,7 +1282,7 @@ class FreqtradeBot(LoggingMixin):
# Send the message
self.rpc.send_msg(msg)
def _notify_exit_cancel(self, trade: Trade, order_type: str, reason: str) -> 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.
"""
@ -1315,6 +1317,8 @@ class FreqtradeBot(LoggingMixin):
'stake_currency': self.config['stake_currency'],
'fiat_currency': self.config.get('fiat_display_currency', None),
'reason': reason,
'sub_trade': sub_trade,
'stake_amount': trade.stake_amount,
}
if 'fiat_display_currency' in self.config:
@ -1330,7 +1334,7 @@ class FreqtradeBot(LoggingMixin):
#
def update_trade_state(self, trade: Trade, order_id: str, action_order: Dict[str, Any] = None,
stoploss_order: bool = False, send_msg: bool = True) -> 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
Handles closing both buy and sell orders.
@ -1363,7 +1367,7 @@ class FreqtradeBot(LoggingMixin):
order = self.handle_order_fee(trade, order)
trade.update(order)
trade.update(order,sub_trade=sub_trade)
trade.recalc_trade_from_orders()
Trade.commit()

View File

@ -116,7 +116,7 @@ class Order(_DECL_BASE):
ft_order_side = Column(String(25), nullable=False)
ft_pair = Column(String(25), nullable=False)
ft_is_open = Column(Boolean, nullable=False, default=True, index=True)
is_recovered = Column(Boolean, nullable=False, default=False)
order_id = Column(String(255), nullable=False, index=True)
status = Column(String(255), nullable=True)
symbol = Column(String(25), nullable=True)
@ -481,9 +481,17 @@ class LocalTrade():
orders=(self.select_filled_orders('buy'))
lbuy=orders[-2]
lamount = (lbuy.filled or lbuy.amount)
lbuy.average=(lbuy.average * lamount - self.calc_profit2(orders[-1].rate, order.rate, order.filled or order.amount))/lamount
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_recovered=True
self.update_order(orders[-1])
# self.orders.remove(orders[-1])
self.update_order(lbuy)
Order.query.session.commit()
self.orders.remove(orders[-1])
self.recalc_trade_from_orders()
Trade.commit()
else:
@ -499,8 +507,11 @@ class LocalTrade():
raise ValueError(f'Unknown order type: {order_type}')
Trade.commit()
def calc_profit2(self, open_rate: float, close_rate: float, amount: Float) ->float:
return Decimal(self.amount) *( (1-self.fee_close)* Decimal(close_rate) -(1+self.fee_open)* Decimal(open_rate) )
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) ))
def close(self, rate: float, *, show_msg: bool = True) -> None:
"""
Sets close_rate to the given rate, calculates total profit
@ -638,6 +649,7 @@ class LocalTrade():
for o in self.orders:
if (o.ft_is_open or
(o.ft_order_side != 'buy') or
o.is_recovered==True or
(o.status not in NON_OPEN_EXCHANGE_STATES)):
continue
@ -695,6 +707,7 @@ class LocalTrade():
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
(o.filled or 0) > 0 and
o.is_recovered==False and
o.status in NON_OPEN_EXCHANGE_STATES]
@property

View File

@ -246,10 +246,10 @@ class Telegram(RPCHandler):
total, msg['stake_currency'], msg['fiat_currency'])
else:
total_fiat = 0
message += f"*Total:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}"
message += f"*Total:* `({round_coin_value(total, msg['stake_currency'])}"
if msg.get('fiat_currency', None):
message += f", {round_coin_value(total, msg['fiat_currency'])}"
message += f", {round_coin_value(total_fiat, msg['fiat_currency'])}"
message += ")`"
if msg.get('sub_trade'):

View File

@ -1037,6 +1037,8 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
'open_date': ANY,
'close_date': ANY,
'close_rate': ANY,
'stake_amount': 0.0009999999999054,
'sub_trade': False
} == last_msg
@ -1102,6 +1104,8 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
'open_date': ANY,
'close_date': ANY,
'close_rate': ANY,
'stake_amount': 0.0009999999999054,
'sub_trade': False
} == last_msg
@ -1157,6 +1161,8 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
'open_date': ANY,
'close_date': ANY,
'close_rate': ANY,
'stake_amount': 0.0009999999999054,
'sub_trade': False
} == msg
@ -1734,7 +1740,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog) -> None:
'pair': 'ETH/BTC',
'limit': 1.099e-05,
'order_type': 'limit',
'stake_amount': 0.001,
'stake_amount': 0.01465333,
'stake_amount_fiat': 0.0,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
@ -1751,7 +1757,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog) -> None:
'*Amount:* `1333.33333333`\n' \
'*Open Rate:* `0.00001099`\n' \
'*Current Rate:* `0.00001099`\n' \
'*Total:* `(0.00100000 BTC, 12.345 USD)`'
'*Total:* `(0.01465333 BTC, 180.895 USD)`'
freqtradebot.config['telegram']['notification_settings'] = {'buy': 'off'}
caplog.clear()
@ -1825,7 +1831,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker) -> None:
'buy_tag': 'buy_signal_01',
'exchange': 'Binance',
'pair': 'ETH/BTC',
'stake_amount': 0.001,
'stake_amount': 0.01465333,
# 'stake_amount_fiat': 0.0,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
@ -1839,7 +1845,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker) -> None:
'*Buy Tag:* `buy_signal_01`\n' \
'*Amount:* `1333.33333333`\n' \
'*Open Rate:* `0.00001099`\n' \
'*Total:* `(0.00100000 BTC, 12.345 USD)`'
'*Total:* `(0.01465333 BTC, 180.895 USD)`'
def test_send_msg_sell_notification(default_conf, mocker) -> None:
@ -2031,7 +2037,7 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None:
'pair': 'ETH/BTC',
'limit': 1.099e-05,
'order_type': 'limit',
'stake_amount': 0.001,
'stake_amount': 0.01465333,
'stake_amount_fiat': 0.0,
'stake_currency': 'BTC',
'fiat_currency': None,
@ -2044,7 +2050,7 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None:
'*Amount:* `1333.33333333`\n'
'*Open Rate:* `0.00001099`\n'
'*Current Rate:* `0.00001099`\n'
'*Total:* `(0.00100000 BTC)`')
'*Total:* `(0.01465333 BTC)`')
def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:

View File

@ -4320,7 +4320,6 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
get_fee=fee,
)
pair = 'ETH/USDT'
# Initial buy
closed_successful_buy_order = {
'pair': pair,
@ -4385,7 +4384,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
'status': None,
'price': 9,
'amount': 12,
'cost': 100,
'cost': 108,
'ft_is_open': True,
'id': '651',
'order_id': '651'
@ -4532,7 +4531,46 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
# Make sure the closed order is found as the second order.
order = trade.select_order('buy', False)
assert order.order_id == '652'
closed_sell_dca_order_1 = {
'ft_pair': pair,
'status': 'closed',
'ft_order_side': 'sell',
'side': 'sell',
'type': 'limit',
'price': 8,
'average': 8,
'amount': 15,
'filled': 15,
'cost': 120,
'ft_is_open': False,
'id': '653',
'order_id': '653'
}
mocker.patch('freqtrade.exchange.Exchange.create_order',
MagicMock(return_value=closed_sell_dca_order_1))
mocker.patch('freqtrade.exchange.Exchange.fetch_order',
MagicMock(return_value=closed_sell_dca_order_1))
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=closed_sell_dca_order_1))
assert freqtrade.execute_trade_exit(trade=trade, limit=8,
sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS),sub_trade_amt=15)
# Assert trade is as expected (averaged dca)
trade = Trade.query.first()
print(trade.open_rate,trade.amount,trade.stake_amount,'DEBUG')
assert trade
assert trade.open_order_id is None
assert trade.amount == 22
assert trade.stake_amount == 203.5625
assert pytest.approx(trade.open_rate) == 9.252840909090908
orders = Order.query.all()
assert orders
assert len(orders) == 4
# Make sure the closed order is found as the second order.
order = trade.select_order('sell', False)
assert order.order_id == '653'
def test_process_open_trade_positions_exception(mocker, default_conf_usdt, fee, caplog) -> None:
default_conf_usdt.update({