Example #1
0
def test_returns_latest_buy_signal(mocker):
    buydf = DataFrame([{'buy': 1, 'date': arrow.utcnow()}])
    mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf)
    assert get_buy_signal('BTC-ETH')

    buydf = DataFrame([{'buy': 0, 'date': arrow.utcnow()}])
    mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf)
    assert not get_buy_signal('BTC-ETH')
Example #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)
Example #3
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
Example #4
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
    for _pair in whitelist:
        if get_buy_signal(_pair):
            pair = _pair
            break
    else:
        return None

    open_rate = get_target_bid(exchange.get_ticker(pair))
    amount = stake_amount / open_rate
    order_id = exchange.buy(pair, open_rate, amount)

    # Create trade entity and return
    message = '*{}:* Buying [{}]({}) at rate `{:f}`'.format(
        exchange.EXCHANGE.name.upper(),
        pair.replace('_', '/'),
        exchange.get_pair_detail_url(pair),
        open_rate
    )
    logger.info(message)
    telegram.send_msg(message)
    return Trade(pair=pair,
                 stake_amount=stake_amount,
                 open_rate=open_rate,
                 open_date=datetime.utcnow(),
                 amount=amount,
                 exchange=exchange.EXCHANGE.name.upper(),
                 open_order_id=order_id,
                 is_open=True)
Example #5
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'
        )