Exemple #1
0
def should_sell(trade: Trade, current_rate: float,
                current_time: datetime) -> bool:
    """
    Based an earlier trade and current price and configuration, decides whether bot should sell
    :return True if bot should sell at current rate
    """

    # todo: query model to see if more gains are possible

    # get current profit
    current_profit = trade.calc_profit(current_rate)

    # check how much is available and determine if above dust trade
    available = exchange.get_available_balance(get_quote_token(str(
        trade.pair)))
    satoshi = 1e-08
    dust_trade_sat = 50000 * satoshi
    trade_amount_btc = available * current_rate
    if trade_amount_btc < dust_trade_sat:
        logger.debug('Trade is DUST')
        logger.debug('Threshold not reached. (cur_profit: %1.2f%%)',
                     current_profit * 100.0)
        logger.debug('Current rate: {}'.format(current_rate))
        return False

    # determine if stoploss is hit
    if 'stoploss' in _CONF and current_profit < float(_CONF['stoploss']):
        logger.debug('Stop loss hit.')
        return True

    # check model (before minimal rois)
    if analyzer.name == 'danml':
        # check if ema-5 is greater than last minute to continue
        # todo: also make sure previous is lower than current
        if get_ema_signal(trade.pair, 1, exchange.get_name()):
            if get_buy_signal(trade.pair, exchange.get_name(), analyzer):
                logger.debug('Threshold not reached. (cur_profit: %1.2f%%)',
                             current_profit * 100.0)
                logger.debug('Current rate: {}'.format(current_rate))
                return False

    # check minimal rois
    for duration, threshold in sorted(_CONF['minimal_roi'].items()):
        # Check if time matches and current rate is above threshold
        time_diff = (current_time - trade.open_date).total_seconds() / 60
        if time_diff > float(duration) and current_profit > threshold:
            return True

    logger.debug('Threshold not reached. (cur_profit: %1.2f%%)',
                 current_profit * 100.0)
    logger.debug('Current rate: {}'.format(current_rate))
    return False
Exemple #2
0
def create_trade(stake_amount: float) -> Optional[Trade]:
    """
    Checks the implemented trading indicator(s) for a randomly picked pair,
    if one pair triggers the buy_signal a new trade record gets created
    :param stake_amount: amount of btc to spend
    """
    logger.info(
        'Checking buy signals to create a new trade with stake_amount: %f ...',
        stake_amount)
    whitelist = copy.deepcopy(_CONF['exchange']['pair_whitelist'])
    # Check if stake_amount is fulfilled
    if exchange.get_balance(_CONF['stake_currency']) < stake_amount:
        raise ValueError('stake amount is not fulfilled (currency={})'.format(
            _CONF['stake_currency']))

    # Remove currently opened and latest pairs from whitelist
    for trade in Trade.query.filter(Trade.is_open.is_(True)).all():
        if trade.pair in whitelist:
            whitelist.remove(trade.pair)
            logger.debug('Ignoring %s in pair whitelist', trade.pair)
    if not whitelist:
        raise ValueError('No pair in whitelist')

    # Pick pair based on StochRSI buy signals
    for _pair in whitelist:
        if get_buy_signal(_pair):
            pair = _pair
            break
    else:
        return None

    # Calculate amount and subtract fee
    fee = exchange.get_fee()
    buy_limit = get_target_bid(exchange.get_ticker(pair))
    amount = (1 - fee) * stake_amount / buy_limit

    order_id = exchange.buy(pair, buy_limit, amount)
    # Create trade entity and return
    message = '*{}:* Buying [{}]({}) with limit `{:.8f}`'.format(
        exchange.get_name().upper(), pair.replace('_', '/'),
        exchange.get_pair_detail_url(pair), buy_limit)
    logger.info(message)
    telegram.send_msg(message)
    # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
    return Trade(pair=pair,
                 stake_amount=stake_amount,
                 amount=amount,
                 fee=fee * 2,
                 open_rate=buy_limit,
                 open_date=datetime.utcnow(),
                 exchange=exchange.get_name().upper(),
                 open_order_id=order_id)
Exemple #3
0
def test_get_name(default_conf, mocker):
    mocker.patch('freqtrade.exchange.validate_pairs',
                 side_effect=lambda s: True)
    default_conf['exchange']['name'] = 'bittrex'
    init(default_conf)

    assert get_name() == 'Bittrex'
Exemple #4
0
def test_get_name(default_conf, mocker):
    mocker.patch('freqtrade.exchange.validate_pairs',
                 side_effect=lambda s: True)
    default_conf['exchange']['name'] = 'bittrex'
    init(default_conf)

    assert get_name() == 'Bittrex'
Exemple #5
0
def refresh_whitelist(whitelist: Optional[List[str]] = None) -> None:
    """
    Check wallet health and remove pair from whitelist if necessary
    :param whitelist: a new whitelist (optional)
    :return: None
    """
    whitelist = whitelist or _CONF['exchange']['pair_whitelist']

    sanitized_whitelist = []
    health = exchange.get_wallet_health()
    for status in health:
        if exchange.get_name() == 'HitBTC':
            pair = status['Currency']
        else:
            pair = '{}_{}'.format(_CONF['stake_currency'], status['Currency'])
        if pair not in whitelist:
            continue
        if status['IsActive']:
            sanitized_whitelist.append(pair)
        else:
            logger.info('Ignoring %s from whitelist (reason: %s).', pair,
                        status.get('Notice') or 'wallet is not active')
    if _CONF['exchange']['pair_whitelist'] != sanitized_whitelist:
        logger.debug('Using refreshed pair whitelist: %s ...',
                     sanitized_whitelist)
        _CONF['exchange']['pair_whitelist'] = sanitized_whitelist

        if analyzer.name == 'cryptoml':
            analyzer.whitelist = sanitized_whitelist
            analyzer.reset_buffer()
Exemple #6
0
def test_exchange_misc(mocker):
    api_mock = MagicMock()
    mocker.patch('freqtrade.exchange._API', api_mock)
    exchange.get_markets()
    assert api_mock.get_markets.call_count == 1
    exchange.get_market_summaries()
    assert api_mock.get_market_summaries.call_count == 1
    api_mock.name = 123
    assert exchange.get_name() == 123
    api_mock.fee = 456
    assert exchange.get_fee() == 456
    exchange.get_wallet_health()
    assert api_mock.get_wallet_health.call_count == 1
Exemple #7
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
Exemple #8
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)
Exemple #9
0
    def create_trade(self) -> bool:
        """
        Checks the implemented trading indicator(s) for a randomly picked pair,
        if one pair triggers the buy_signal a new trade record gets created
        :param stake_amount: amount of btc to spend
        :param interval: Ticker interval used for Analyze
        :return: True if a trade object has been created and persisted, False otherwise
        """
        stake_amount = self.config['stake_amount']
        interval = self.analyze.get_ticker_interval()

        logger.info(
            'Checking buy signals to create a new trade with stake_amount: %f ...',
            stake_amount)
        whitelist = copy.deepcopy(self.config['exchange']['pair_whitelist'])
        # Check if stake_amount is fulfilled
        if exchange.get_balance(self.config['stake_currency']) < stake_amount:
            raise DependencyException(
                'stake amount is not fulfilled (currency={})'.format(
                    self.config['stake_currency']))

        # Remove currently opened and latest pairs from whitelist
        for trade in Trade.query.filter(Trade.is_open.is_(True)).all():
            if trade.pair in whitelist:
                whitelist.remove(trade.pair)
                logger.debug('Ignoring %s in pair whitelist', trade.pair)

        if not whitelist:
            raise DependencyException('No currency pairs in whitelist')

        # Pick pair based on StochRSI buy signals
        for _pair in whitelist:
            (buy, sell) = self.analyze.get_signal(_pair, interval)
            if buy and not sell:
                pair = _pair
                break
        else:
            return False

        # Calculate amount
        buy_limit = self.get_target_bid(exchange.get_ticker(pair))
        amount = stake_amount / buy_limit

        order_id = exchange.buy(pair, buy_limit, amount)

        stake_amount_fiat = self.fiat_converter.convert_amount(
            stake_amount, self.config['stake_currency'],
            self.config['fiat_display_currency'])

        # Create trade entity and return
        self.rpc.send_msg(
            '*{}:* Buying [{}]({}) with limit `{:.8f} ({:.6f} {}, {:.3f} {})` '
            .format(exchange.get_name().upper(), pair.replace('_', '/'),
                    exchange.get_pair_detail_url(pair), buy_limit,
                    stake_amount, self.config['stake_currency'],
                    stake_amount_fiat, self.config['fiat_display_currency']))
        # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
        trade = Trade(pair=pair,
                      stake_amount=stake_amount,
                      amount=amount,
                      fee=exchange.get_fee(),
                      open_rate=buy_limit,
                      open_date=datetime.utcnow(),
                      exchange=exchange.get_name().upper(),
                      open_order_id=order_id)
        Trade.session.add(trade)
        Trade.session.flush()
        return True
Exemple #10
0
def create_trade(stake_amount: float) -> bool:
    """
    Checks the implemented trading indicator(s) for a randomly picked pair,
    if one pair triggers the buy_signal a new trade record gets created
    :param stake_amount: amount of btc to spend
    :return: True if a trade object has been created and persisted, False otherwise
    """
    logger.info(
        'Checking buy signals to create a new trade with stake_amount: %f ...',
        stake_amount
    )
    whitelist = copy.deepcopy(_CONF['exchange']['pair_whitelist'])
    # Check if stake_amount is fulfilled
    if exchange.get_balance(_CONF['stake_currency']) < stake_amount:
        raise DependencyException(
            'stake amount is not fulfilled (currency={})'.format(_CONF['stake_currency'])
        )

    # Remove currently opened and latest pairs from whitelist
    for trade in Trade.query.filter(Trade.is_open.is_(True)).all():
        if trade.pair in whitelist:
            whitelist.remove(trade.pair)
            logger.debug('Ignoring %s in pair whitelist', trade.pair)
    if not whitelist:
        raise DependencyException('No pair in whitelist')

    # Pick pair based on StochRSI buy signals
    for _pair in whitelist:
        if get_signal(_pair, SignalType.BUY):
            pair = _pair
            break
    else:
        return False

    # Calculate amount
    buy_limit = get_target_bid(exchange.get_ticker(pair))
    amount = stake_amount / buy_limit

    order_id = exchange.buy(pair, buy_limit, amount)

    fiat_converter = CryptoToFiatConverter()
    stake_amount_fiat = fiat_converter.convert_amount(
        stake_amount,
        _CONF['stake_currency'],
        _CONF['fiat_display_currency']
    )

    # Create trade entity and return
    rpc.send_msg('*{}:* Buying [{}]({}) with limit `{:.8f} ({:.6f} {}, {:.3f} {})` '.format(
        exchange.get_name().upper(),
        pair.replace('_', '/'),
        exchange.get_pair_detail_url(pair),
        buy_limit, stake_amount, _CONF['stake_currency'],
        stake_amount_fiat, _CONF['fiat_display_currency']
    ))
    # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
    trade = Trade(
        pair=pair,
        stake_amount=stake_amount,
        amount=amount,
        fee=exchange.get_fee(),
        open_rate=buy_limit,
        open_date=datetime.utcnow(),
        exchange=exchange.get_name().upper(),
        open_order_id=order_id
    )
    Trade.session.add(trade)
    Trade.session.flush()
    return True
Exemple #11
0
def create_trade(stake_amount: float) -> Optional[Trade]:
    """
    Checks the implemented trading indicator(s) for a randomly picked pair,
    if one pair triggers the buy_signal a new trade record gets created
    :param stake_amount: amount of btc to spend
    """
    logger.info('Creating new trade with stake_amount: %f ...', stake_amount)
    whitelist = copy.deepcopy(_CONF['exchange']['pair_whitelist'])
    # Check if stake_amount is fulfilled
    if exchange.get_balance(_CONF['stake_currency']) < stake_amount:
        raise ValueError('stake amount is not fulfilled (currency={})'.format(
            _CONF['stake_currency']))

    # Remove currently opened and latest pairs from whitelist
    for trade in Trade.query.filter(Trade.is_open.is_(True)).all():
        if trade.pair in whitelist:
            whitelist.remove(trade.pair)
            logger.debug('Ignoring %s in pair whitelist', trade.pair)
    # if not whitelist:
    #     raise ValueError('No pair in whitelist')

    # Pick pair based on StochRSI buy signals
    if analyzer.name == 'danml':
        for _pair in whitelist:
            if get_buy_signal(_pair, exchange.get_name(), analyzer):
                pair = _pair
                break
        else:
            return None
    elif analyzer.name == 'cryptoml':
        update = False
        if datetime.utcnow().minute % 5 == 0:
            update = True
        pair = analyzer.get_buy_signal(whitelist,
                                       update=update,
                                       threshold=0.01,
                                       repeats=3)
        if pair is None:
            return None

    # Calculate amount and subtract fee
    fee = exchange.get_fee()
    buy_limit = get_target_bid(exchange.get_ticker(pair))
    amount = (1 - fee) * stake_amount / buy_limit

    health = exchange.get_wallet_health()
    if exchange.get_name() == 'HitBTC':
        token = pair
    else:
        token = get_quote_token(pair)
    token_healthy = False
    for status in health:
        if status['Currency'] == token:
            token_healthy = status['IsActive']
    if token_healthy:
        order_id = exchange.buy(pair, buy_limit, amount)
        # Create trade entity and return
        message = '*{}:* Buying [{}]({}) with limit `{:.8f}`'.format(
            exchange.get_name().upper(), pair.replace('_', '/'),
            exchange.get_pair_detail_url(pair), buy_limit)
        logger.info(message)
        telegram.send_msg(message)
        # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
        return Trade(
            pair=pair,
            stake_amount=stake_amount,
            amount=amount,
            fee=fee * 2.,
            open_rate=buy_limit,
            open_date=datetime.utcnow(),
            exchange=exchange.get_name().upper(),
            open_order_id=order_id,
            # open_order_type='buy'
        )
Exemple #12
0

# ensure directory exists
base_path = os.path.join(os.path.expanduser('~'), 'freqtrade')

# get configuration
with open(os.path.join(base_path, 'config.json')) as file:
	_CONF = json.load(file)

# initialize the exchange
exchange.init(_CONF)

# get ticker
data = exchange.get_ticker(pair='ETH_BTC')
print(data)


# get ticker history
df = exchange.get_ticker_history(pair='ETH_BTC', tick_interval=1)
print(pd.DataFrame(df))

# get markets
data = exchange.get_markets()
print(data)

# get name
print(exchange.get_name())

print(exchange.get_sleep_time())
print(exchange.get_fee())