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`')
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)
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])
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)
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')
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')
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)
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)
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)
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)
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)
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')
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')
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