Example #1
0
    def handle_timedout_limit_buy(self, trade: Trade, order: Dict) -> bool:
        """Buy timeout - cancel order
        :return: True if order was fully cancelled
        """
        exchange.cancel_order(trade.open_order_id)
        if order['remaining'] == order['amount']:
            # if trade is not partially completed, just delete the trade
            Trade.session.delete(trade)
            # FIX? do we really need to flush, caller of
            #      check_handle_timedout will flush afterwards
            Trade.session.flush()
            logger.info('Buy order timeout for %s.', trade)
            self.rpc.send_msg(
                '*Timeout:* Unfilled buy order for {} cancelled'.format(
                    trade.pair.replace('_', '/')))
            return True

        # if trade is partially complete, edit the stake details for the trade
        # and close the order
        trade.amount = order['amount'] - order['remaining']
        trade.stake_amount = trade.amount * trade.open_rate
        trade.open_order_id = None
        logger.info('Partial buy order timeout for %s.', trade)
        self.rpc.send_msg(
            '*Timeout:* Remaining buy order for {} cancelled'.format(
                trade.pair.replace('_', '/')))
        return False
Example #2
0
def handle_trade(trade: Trade) -> bool:
    """
    Sells the current pair if the threshold is reached and updates the trade record.
    :return: True if trade has been sold, False otherwise
    """
    if not trade.is_open:
        raise ValueError('attempt to handle closed trade: {}'.format(trade))

    logger.debug('Handling %s ...', trade)

    # first determine if buy order that is still open
    if trade.open_order_id:
        order_info = exchange.get_order(trade.open_order_id)
        order_type = order_info['type']
        if order_type == 'LIMIT_BUY':
            max_open_time = 10
            current_time = datetime.utcnow()
            amount_minutes_open = (current_time -
                                   trade.open_date).total_seconds() / 60.
            if amount_minutes_open > max_open_time:
                health = exchange.get_wallet_health()
                if exchange.get_name() == 'HitBTC':
                    token = trade.pair
                else:
                    token = get_quote_token(trade.pair)
                token_healthy = False
                for status in health:
                    if status['Currency'] == token:
                        token_healthy = status['IsActive']
                if token_healthy:
                    logger.debug('Cancelling %s ...', trade)
                    exchange.cancel_order(trade.open_order_id)
                    # trade.is_open = 0
                    # trade.open_order_id = None
                    Trade.session.delete(trade)
                else:
                    logger.debug(
                        'Cancelling could not execute due to wallet heath for %s ...',
                        trade)
                return False

    current_rate = exchange.get_ticker(trade.pair)['bid']  # ask?
    if current_rate is None:
        return False
    if should_sell(trade, current_rate, datetime.utcnow()):
        execute_sell(trade, current_rate)
        return True
    return False
Example #3
0
def test_cancel_order(default_conf, mocker):
    default_conf['dry_run'] = False
    mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
    api_mock = MagicMock()
    api_mock.cancel_order = MagicMock(return_value=123)
    mocker.patch('freqtrade.exchange._API', api_mock)
    assert cancel_order(order_id='_') == 123
Example #4
0
def check_handle_timedout(timeoutvalue: int) -> None:
    """
    Check if any orders are timed out and cancel if neccessary
    :param timeoutvalue: Number of minutes until order is considered timed out
    :return: None
    """
    timeoutthreashold = arrow.utcnow().shift(minutes=-timeoutvalue).datetime

    for trade in Trade.query.filter(Trade.open_order_id.isnot(None)).all():
        order = exchange.get_order(trade.open_order_id)
        ordertime = arrow.get(order['opened'])

        if order['type'] == "LIMIT_BUY" and ordertime < timeoutthreashold:
            # Buy timeout - cancel order
            exchange.cancel_order(trade.open_order_id)
            if order['remaining'] == order['amount']:
                # if trade is not partially completed, just delete the trade
                Trade.session.delete(trade)
                Trade.session.flush()
                logger.info('Buy order timeout for %s.', trade)
            else:
                # if trade is partially complete, edit the stake details for the trade
                # and close the order
                trade.amount = order['amount'] - order['remaining']
                trade.stake_amount = trade.amount * trade.open_rate
                trade.open_order_id = None
                logger.info('Partial buy order timeout for %s.', trade)
        elif order['type'] == "LIMIT_SELL" and ordertime < timeoutthreashold:
            # Sell timeout - cancel order and update trade
            if order['remaining'] == order['amount']:
                # if trade is not partially completed, just cancel the trade
                exchange.cancel_order(trade.open_order_id)
                trade.close_rate = None
                trade.close_profit = None
                trade.close_date = None
                trade.is_open = True
                trade.open_order_id = None
                logger.info('Sell order timeout for %s.', trade)
                return True
            else:
                # TODO: figure out how to handle partially complete sell orders
                pass
Example #5
0
def check_handle_timedout(timeoutvalue: int) -> None:
    """
    Check if any orders are timed out and cancel if neccessary
    :param timeoutvalue: Number of minutes until order is considered timed out
    :return: None
    """
    timeoutthreashold = arrow.utcnow().shift(minutes=-timeoutvalue).datetime

    for trade in Trade.query.filter(Trade.open_order_id.isnot(None)).all():
        order = exchange.get_order(trade.open_order_id)
        ordertime = arrow.get(order['opened'])

        if order['type'] == "LIMIT_BUY" and ordertime < timeoutthreashold:
            # Buy timeout - cancel order
            exchange.cancel_order(trade.open_order_id)
            if order['remaining'] == order['amount']:
                # if trade is not partially completed, just delete the trade
                Trade.session.delete(trade)
                Trade.session.flush()
                logger.info('Buy order timeout for %s.', trade)
            else:
                # if trade is partially complete, edit the stake details for the trade
                # and close the order
                trade.amount = order['amount'] - order['remaining']
                trade.stake_amount = trade.amount * trade.open_rate
                trade.open_order_id = None
                logger.info('Partial buy order timeout for %s.', trade)
        elif order['type'] == "LIMIT_SELL" and ordertime < timeoutthreashold:
            # Sell timeout - cancel order and update trade
            if order['remaining'] == order['amount']:
                # if trade is not partially completed, just cancel the trade
                exchange.cancel_order(trade.open_order_id)
                trade.close_rate = None
                trade.close_profit = None
                trade.close_date = None
                trade.is_open = True
                trade.open_order_id = None
                logger.info('Sell order timeout for %s.', trade)
                return True
            else:
                # TODO: figure out how to handle partially complete sell orders
                pass
Example #6
0
def _exec_forcesell(trade: Trade) -> None:
    # Check if there is there is an open order
    if trade.open_order_id:
        order = exchange.get_order(trade.open_order_id)

        # Cancel open LIMIT_BUY orders and close trade
        if order and not order['closed'] and order['type'] == 'LIMIT_BUY':
            exchange.cancel_order(trade.open_order_id)
            trade.close(order.get('rate') or trade.open_rate)
            # TODO: sell amount which has been bought already
            return

        # Ignore trades with an attached LIMIT_SELL order
        if order and not order['closed'] and order['type'] == 'LIMIT_SELL':
            return

    # Get current rate and execute sell
    current_rate = exchange.get_ticker(trade.pair, False)['bid']
    from freqtrade.main import execute_sell
    execute_sell(trade, current_rate)
Example #7
0
def _exec_forcesell(trade: Trade) -> None:
    # Check if there is there is an open order
    if trade.open_order_id:
        order = exchange.get_order(trade.open_order_id)

        # Cancel open LIMIT_BUY orders and close trade
        if order and not order['closed'] and order['type'] == 'LIMIT_BUY':
            exchange.cancel_order(trade.open_order_id)
            trade.close(order.get('rate') or trade.open_rate)
            # TODO: sell amount which has been bought already
            return

        # Ignore trades with an attached LIMIT_SELL order
        if order and not order['closed'] and order['type'] == 'LIMIT_SELL':
            return

    # Get current rate and execute sell
    current_rate = exchange.get_ticker(trade.pair, False)['bid']
    from freqtrade.main import execute_sell
    execute_sell(trade, current_rate)
Example #8
0
    def handle_timedout_limit_sell(self, trade: Trade, order: Dict) -> bool:
        """
        Sell timeout - cancel order and update trade
        :return: True if order was fully cancelled
        """
        if order['remaining'] == order['amount']:
            # if trade is not partially completed, just cancel the trade
            exchange.cancel_order(trade.open_order_id)
            trade.close_rate = None
            trade.close_profit = None
            trade.close_date = None
            trade.is_open = True
            trade.open_order_id = None
            self.rpc.send_msg(
                '*Timeout:* Unfilled sell order for {} cancelled'.format(
                    trade.pair.replace('_', '/')))
            logger.info('Sell order timeout for %s.', trade)
            return True

        # TODO: figure out how to handle partially complete sell orders
        return False
Example #9
0
def execute_sell(trade: Trade, limit: float) -> None:
    """
    Executes a limit sell for the given trade and limit
    :param trade: Trade instance
    :param limit: limit rate for the sell order
    :return: None
    """

    # check how much is available
    available = exchange.get_available_balance(get_quote_token(str(
        trade.pair)))

    # Execute sell and update trade record
    order_id = exchange.sell(str(trade.pair), limit, available)  # trade.amount
    trade.open_order_id = order_id

    if available < trade.amount:

        # cancel the rest
        # todo: check if wallet is healthy before cancelling
        health = exchange.get_wallet_health()
        if exchange.get_name() == 'HitBTC':
            token = trade.pair
        else:
            token = get_quote_token(trade.pair)
        token_healthy = False
        for status in health:
            if status['Currency'] == token:
                token_healthy = status['IsActive']
        if token_healthy:
            exchange.cancel_order(trade.id)

    fmt_exp_profit = round(trade.calc_profit(limit) * 100, 2)
    message = '*{}:* Selling [{}]({}) with limit `{:.8f} (profit: ~{:.2f}%)`'.format(
        trade.exchange, trade.pair.replace('_', '/'),
        exchange.get_pair_detail_url(trade.pair), limit, fmt_exp_profit)
    logger.info(message)
    telegram.send_msg(message)
Example #10
0
def test_cancel_order_dry_run(default_conf, mocker):
    default_conf['dry_run'] = True
    mocker.patch.dict('freqtrade.exchange._CONF', default_conf)

    assert cancel_order(order_id='123') is None
Example #11
0
def test_cancel_order_dry_run(default_conf, mocker):
    default_conf['dry_run'] = True
    mocker.patch.dict('freqtrade.exchange._CONF', default_conf)

    assert cancel_order(order_id='123') is None