Пример #1
0
def app(config: dict) -> None:
    """
    Main function which handles the application state
    :param config: config as dict
    :return: None
    """
    logger.info('Starting freqtrade %s', __version__)
    init(config)
    try:
        old_state = get_state()
        logger.info('Initial State: %s', old_state)
        telegram.send_msg('*Status:* `{}`'.format(old_state.name.lower()))
        while True:
            new_state = get_state()
            # Log state transition
            if new_state != old_state:
                telegram.send_msg('*Status:* `{}`'.format(new_state.name.lower()))
                logging.info('Changing state to: %s', new_state.name)

            if new_state == State.STOPPED:
                time.sleep(1)
            elif new_state == State.RUNNING:
                _process()
                # We need to sleep here because otherwise we would run into bittrex rate limit
                time.sleep(25)
            old_state = new_state
    except RuntimeError:
        telegram.send_msg('*Status:* Got RuntimeError: ```\n{}\n```'.format(traceback.format_exc()))
        logger.exception('RuntimeError. Trader stopped!')
    finally:
        telegram.send_msg('*Status:* `Trader has stopped`')
Пример #2
0
    def test_5_start_handle(self):
        with patch.dict('main._CONF', self.conf):
            msg_mock = MagicMock()
            with patch.multiple('main.telegram',
                                _CONF=self.conf,
                                init=MagicMock(),
                                send_msg=msg_mock):
                init(self.conf, 'sqlite://')

                update_state(State.STOPPED)
                self.assertEqual(get_state(), State.STOPPED)
                _start(bot=MagicBot(), update=self.update)
                self.assertEqual(get_state(), State.RUNNING)
                self.assertEqual(msg_mock.call_count, 0)
Пример #3
0
    def test_6_stop_handle(self):
        with patch.dict('main._CONF', self.conf):
            msg_mock = MagicMock()
            with patch.multiple('main.telegram',
                                _CONF=self.conf,
                                init=MagicMock(),
                                send_msg=msg_mock):
                init(self.conf, 'sqlite://')

                update_state(State.RUNNING)
                self.assertEqual(get_state(), State.RUNNING)
                _stop(bot=MagicBot(), update=self.update)
                self.assertEqual(get_state(), State.STOPPED)
                self.assertEqual(msg_mock.call_count, 1)
                self.assertIn('Stopping trader',
                              msg_mock.call_args_list[0][0][0])
Пример #4
0
def _performance(bot: Bot, update: Update) -> None:
    """
    Handler for /performance.
    Shows a performance statistic from finished trades
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() != State.RUNNING:
        send_msg('`trader is not running`', bot=bot)
        return

    pair_rates = Trade.session.query(Trade.pair, func.sum(Trade.close_profit).label('profit_sum')) \
        .filter(Trade.is_open.is_(False)) \
        .group_by(Trade.pair) \
        .order_by(text('profit_sum DESC')) \
        .all()

    stats = '\n'.join('{index}. <code>{pair}\t{profit:.2f}%</code>'.format(
        index=i + 1, pair=pair, profit=round(rate, 2))
                      for i, (pair, rate) in enumerate(pair_rates))

    message = '<b>Performance:</b>\n{}\n'.format(stats)
    logger.debug(message)
    send_msg(message, parse_mode=ParseMode.HTML)
Пример #5
0
def _cancelorder(bot: Bot, update: Update) -> None:
    """
    Handler for /cancelorder <id>.
    Cancels the given trade
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() != State.RUNNING:
        send_msg('`trader is not running`', bot=bot)
        return

    try:
        trade_id = int(update.message.text.replace('/cancelorder', '').strip())

        # Query for trade
        trade = Trade.query.filter(
            and_(Trade.id == trade_id, Trade.is_open.is_(True))).first()

        print(trade.pair)

        if not trade:
            send_msg('There is no open trade with ID: `{}`'.format(trade_id))
            return
        # Cancel the order - According to test/test_main.py Line 84
        message = messager.get_cancelorder(trade)
        logger.info(message)
        send_msg(message)
        exchange.cancel_order(trade.open_order_id)
        # main.close_trade_if_fulfilled(trade)

    except ValueError:
        send_msg('Invalid argument. Usage: `/closeorder <trade_id>`')
        logger.warning('/closeorder: Invalid argument received')
Пример #6
0
def _forcesell(bot: Bot, update: Update) -> None:
    """
    Handler for /forcesell <id>.
    Sells the given trade at current price
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() != State.RUNNING:
        send_msg('`trader is not running`', bot=bot)
        return

    try:
        trade_id = int(update.message.text.replace('/forcesell', '').strip())
        # Query for trade
        trade = Trade.query.filter(
            and_(Trade.id == trade_id, Trade.is_open.is_(True))).first()
        if not trade:
            send_msg('There is no open trade with ID: `{}`'.format(trade_id))
            return

        message = messager.get_forcesell(trade)

        logger.info(message)
        send_msg(message)
        main.close_trade_if_fulfilled(trade)

    except ValueError:
        send_msg('Invalid argument. Usage: `/forcesell <trade_id>`')
        logger.warning('/forcesell: Invalid argument received')
Пример #7
0
def _start(bot: Bot, update: Update) -> None:
    """
    Handler for /start.
    Starts TradeThread
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() == State.RUNNING:
        send_msg('*Status:* `already running`', bot=bot)
    else:
        update_state(State.RUNNING)
Пример #8
0
def _status(bot: Bot, update: Update) -> None:
    """
    Handler for /status.
    Returns the current TradeThread status
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    # Fetch open trade
    trades = Trade.query.filter(Trade.is_open.is_(True)).all()
    if get_state() != State.RUNNING:
        send_msg('*Status:* `trader is not running`', bot=bot)
    elif not trades:
        send_msg('*Status:* `no active order`', bot=bot)
    else:
        for trade in trades:
            # calculate profit and send message to user
            current_rate = exchange.get_ticker(trade.pair)['bid']
            current_profit = 100 * (
                (current_rate - trade.open_rate) / trade.open_rate)
            orders = exchange.get_open_orders(trade.pair)
            orders = [o for o in orders if o['id'] == trade.open_order_id]
            order = orders[0] if orders else None

            fmt_close_profit = '{:.2f}%'.format(round(
                trade.close_profit, 2)) if trade.close_profit else None
            message = """
*Trade ID:* `{trade_id}`
*Current Pair:* [{pair}]({market_url})
*Open Since:* `{date}`
*Amount:* `{amount}`
*Open Rate:* `{open_rate}`
*Close Rate:* `{close_rate}`
*Current Rate:* `{current_rate}`
*Close Profit:* `{close_profit}`
*Current Profit:* `{current_profit:.2f}%`
*Open Order:* `{open_order}`
            """.format(
                trade_id=trade.id,
                pair=trade.pair,
                market_url=exchange.get_pair_detail_url(trade.pair),
                date=arrow.get(trade.open_date).humanize(),
                open_rate=trade.open_rate,
                close_rate=trade.close_rate,
                current_rate=current_rate,
                amount=round(trade.amount, 8),
                close_profit=fmt_close_profit,
                current_profit=round(current_profit, 2),
                open_order='{} ({})'.format(order['remaining'], order['type'])
                if order else None,
            )
            send_msg(message, bot=bot)
Пример #9
0
def _stop(bot: Bot, update: Update) -> None:
    """
    Handler for /stop.
    Stops TradeThread
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() == State.RUNNING:
        send_msg('`Stopping trader ...`', bot=bot)
        update_state(State.STOPPED)
    else:
        send_msg('*Status:* `already stopped`', bot=bot)
Пример #10
0
def _status(bot: Bot, update: Update) -> None:
    """
    Handler for /status.
    Returns the current TradeThread status
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    # Fetch open trade
    trades = Trade.query.filter(Trade.is_open.is_(True)).all()
    if get_state() != State.RUNNING:
        send_msg('*Status:* `trader is not running`', bot=bot)
    elif not trades:
        send_msg('*Status:* `no active order`', bot=bot)
    else:
        messages = messager.get_status(trades)

        for message in messages:
            send_msg(message, bot=bot)
Пример #11
0
def _performance(bot: Bot, update: Update) -> None:
    """
    Handler for /performance.
    Shows a performance statistic from finished trades
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() != State.RUNNING:
        send_msg('`trader is not running`', bot=bot)
        return

    pair_rates = Trade.session.query(Trade.pair, func.sum(Trade.close_profit).label('profit_sum')) \
        .filter(Trade.is_open.is_(False)) \
        .group_by(Trade.pair) \
        .order_by(text('profit_sum DESC')) \
        .all()

    message = messager.get_performance(pair_rates)
    logger.debug(message)
    send_msg(message, parse_mode=ParseMode.HTML)
Пример #12
0
def _forcesellall(bot: Bot, update: Update) -> None:
    """
    Handler for /forcesellall.
    Sell all trades at current price
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() != State.RUNNING:
        send_msg('`trader is not running`', bot=bot)
        return

    try:
        trades = Trade.query.filter(Trade.is_open.is_(True)).all()

        if len(trades) == 0:
            send_msg('`open trades not found`', bot=bot)
            return

        for trade in trades:
            # Get current rate
            current_rate = exchange.get_ticker(trade.pair)['bid']
            # Get available balance
            currency = trade.pair.split('_')[1]
            balance = exchange.get_balance(currency)
            # Execute sell
            profit = trade.exec_sell_order(current_rate, balance)
            message = '*{}:* Selling [{}]({}) at rate `{:f} (profit: {}%)`'.format(
                trade.exchange.name, trade.pair.replace('_', '/'),
                exchange.get_pair_detail_url(trade.pair), trade.close_rate,
                round(profit, 2))
            logger.info(message)
            send_msg(message)
            time.sleep(25)

    except ValueError:
        send_msg('Failed to sell all trades')
        logger.warning('/forcesellall: Failed to sell all trades')
Пример #13
0
def _forcesell(bot: Bot, update: Update) -> None:
    """
    Handler for /forcesell <id>.
    Sells the given trade at current price
    :param bot: telegram bot
    :param update: message update
    :return: None
    """
    if get_state() != State.RUNNING:
        send_msg('`trader is not running`', bot=bot)
        return

    try:
        trade_id = int(update.message.text.replace('/forcesell', '').strip())
        # Query for trade
        trade = Trade.query.filter(
            and_(Trade.id == trade_id, Trade.is_open.is_(True))).first()
        if not trade:
            send_msg('There is no open trade with ID: `{}`'.format(trade_id))
            return
        # Get current rate
        current_rate = exchange.get_ticker(trade.pair)['bid']
        # Get available balance
        currency = trade.pair.split('_')[1]
        balance = exchange.get_balance(currency)
        # Execute sell
        profit = trade.exec_sell_order(current_rate, balance)
        message = '*{}:* Selling [{}]({}) at rate `{:f} (profit: {}%)`'.format(
            trade.exchange.name, trade.pair.replace('_', '/'),
            exchange.get_pair_detail_url(trade.pair), trade.close_rate,
            round(profit, 2))
        logger.info(message)
        send_msg(message)

    except ValueError:
        send_msg('Invalid argument. Usage: `/forcesell <trade_id>`')
        logger.warning('/forcesell: Invalid argument received')
Пример #14
0
def play():
    cur_iters = 0
    episode_reward = 0

    done = False
    while not done:
        cur_iters += 1
        print("\rIter:", cur_iters, end="", flush=True)

        # alive = list(range(gs.num_agents))
        # preds = np.zeros((gs.num_agents, gs.num_actions))
        states_before = []
        states_after = []
        actions = []
        rewards = []

        gs.reset_markers()
        for agent_idx in range(gs.num_agents):
            # x, y, t, u, h = gs.agents[agent_idx]
            agent_state = get_state(gs, agent_idx, MODEL_TYPE)
            states_before.append(agent_state)

            # Get predicted action
            pred = models[agent_idx].get_action(agent_state)
            if MODEL_TYPE in train_after_episode:
                pred = one_hot(pred, gs.num_actions, float)

            if agent_idx in stochastic:
                action = random.randint(0, gs.num_actions - 1)
            else:
                action = np.argmax(pred)

            # Perform action & get reward
            reward = gs.move_agent(agent_idx, action)
            agent_state = get_state(gs, agent_idx, MODEL_TYPE)
            states_after.append(agent_state)

            episode_reward += reward
            rewards.append(reward)

            if MODEL_TYPE in sac_models:
                actions.append(pred)
            else:
                actions.append(action)

            gs.update_agent_positions()

        # Check stop conditions
        winner = gs.get_winner()
        if winner is not None:
            done = True

            # Add winning reward
            for agent_idx in range(gs.num_agents):
                x, y, t, u, h = gs.agents[agent_idx]

                if t == winner:
                    rewards[agent_idx - gs.num_agents] += 1

        elif cur_iters >= MAX_ITERS:
            done = True

        if PRINT_VISUALS and cur_iters % 100 == 0:
            os.system("clear")
            print(gs.print_game_space())
            print()
            print_state(MODEL_TYPE, cur_iters, episode, episode_reward, gs)

        # Train
        train_after_iter(models, gs, states_before, states_after, actions,
                         rewards, done)

    print()
    print_state(MODEL_TYPE, cur_iters, episode, episode_reward, gs)

    return cur_iters, episode_reward, done