Exemplo n.º 1
0
    def _reduce(self, qty, price):
        if self.is_open is False:
            raise EmptyPosition('The position is closed.')

        # just to prevent confusion
        qty = abs(qty)

        estimated_profit = jh.estimate_PNL(qty, self.entry_price, price,
                                           self.type)

        if self.exchange:
            self.exchange.increase_balance(
                self, qty * self.entry_price + estimated_profit)

        if self.type == trade_types.LONG:
            self.qty -= qty
        elif self.type == trade_types.SHORT:
            self.qty += qty

        info_text = 'REDUCED position: {}, {}, {}, {}, ${}'.format(
            self.exchange_name, self.symbol, self.type, self.qty,
            round(self.entry_price, 2))

        if jh.is_debuggable('position_reduced'):
            logger.info(info_text)

        if jh.is_live(
        ) and config['env']['notifications']['events']['updated_position']:
            notifier.notify(info_text)
Exemplo n.º 2
0
    def _close(self, close_price):
        if self.is_open is False:
            raise EmptyPosition('The position is already closed.')

        # just to prevent confusion
        close_qty = abs(self.qty)

        estimated_profit = jh.estimate_PNL(close_qty, self.entry_price,
                                           close_price, self.type)
        entry = self.entry_price
        trade_type = self.type
        self.exit_price = close_price

        if self.exchange:
            self.exchange.increase_balance(
                self, close_qty * self.entry_price + estimated_profit)
        self.qty = 0
        self.entry_price = None
        self.closed_at = jh.now()

        info_text = 'CLOSED {} position: {}, {}. PNL: ${}, entry: {}, exit: {}'.format(
            trade_type, self.exchange_name, self.symbol,
            round(estimated_profit, 2), entry, close_price)

        if jh.is_debuggable('position_closed'):
            logger.info(info_text)

        if jh.is_live(
        ) and config['env']['notifications']['events']['updated_position']:
            notifier.notify(info_text)
Exemplo n.º 3
0
    def _reduce(self, qty: float, price: float) -> None:
        if self.is_open is False:
            raise EmptyPosition('The position is closed.')

        # just to prevent confusion
        qty = abs(qty)

        estimated_profit = jh.estimate_PNL(qty, self.entry_price, price,
                                           self.type)

        if self.exchange:
            # self.exchange.increase_futures_balance(qty * self.entry_price + estimated_profit)
            self.exchange.add_realized_pnl(estimated_profit)
            self.exchange.temp_reduced_amount[jh.base_asset(
                self.symbol)] += abs(qty * price)

        if self.type == trade_types.LONG:
            self.qty = subtract_floats(self.qty, qty)
        elif self.type == trade_types.SHORT:
            self.qty = sum_floats(self.qty, qty)

        info_text = 'REDUCED position: {}, {}, {}, {}, ${}'.format(
            self.exchange_name, self.symbol, self.type, self.qty,
            round(self.entry_price, 2))

        if jh.is_debuggable('position_reduced'):
            logger.info(info_text)

        if jh.is_live(
        ) and config['env']['notifications']['events']['updated_position']:
            notifier.notify(info_text)
Exemplo n.º 4
0
    def _close(self, close_price: float) -> None:
        if self.is_open is False:
            raise EmptyPosition('The position is already closed.')

        # just to prevent confusion
        close_qty = abs(self.qty)

        estimated_profit = jh.estimate_PNL(close_qty, self.entry_price,
                                           close_price, self.type)
        entry = self.entry_price
        trade_type = self.type
        self.exit_price = close_price

        if self.exchange:
            self.exchange.add_realized_pnl(estimated_profit)
            self.exchange.temp_reduced_amount[jh.base_asset(
                self.symbol)] += abs(close_qty * close_price)
        self.qty = 0
        self.entry_price = None
        self.closed_at = jh.now_to_timestamp()

        if not jh.is_unit_testing():
            info_text = 'CLOSED {} position: {}, {}, {}. PNL: ${}, Balance: ${}, entry: {}, exit: {}'.format(
                trade_type, self.exchange_name, self.symbol,
                self.strategy.name, round(estimated_profit, 2),
                jh.format_currency(
                    round(self.exchange.wallet_balance(self.symbol),
                          2)), entry, close_price)

            if jh.is_debuggable('position_closed'):
                logger.info(info_text)

            if jh.is_live(
            ) and config['env']['notifications']['events']['updated_position']:
                notifier.notify(info_text)
Exemplo n.º 5
0
 def pnl(self):
     """PNL"""
     fee = config['env']['exchanges'][self.exchange]['fee']
     return jh.estimate_PNL(
         self.qty, self.entry_price, self.exit_price,
         self.type, fee
     )
Exemplo n.º 6
0
def test_estimate_PNL():
    # profit
    assert jh.estimate_PNL(2, 50, 60, 'long') == 20
    assert jh.estimate_PNL(2, 60, 50, 'short') == 20

    # loss
    assert jh.estimate_PNL(2, 50, 60, 'short') == -20
    assert jh.estimate_PNL(2, 60, 50, 'long') == -20

    # profit with fee
    assert jh.estimate_PNL(1, 10, 20, 'long', 0.002) == 9.94
    # loss with fee
    assert jh.estimate_PNL(1, 10, 20, 'short', 0.002) == -10.06

    with pytest.raises(TypeError):
        jh.estimate_PNL(1, 200, 220, 1)
        jh.estimate_PNL(1, 200, 'invalid_input', 'short')
        jh.estimate_PNL(1, 'invalid_input', 220, 'short')
        jh.estimate_PNL('invalid_input', 200, 220, 'short')