implement /forcesell command
This commit is contained in:
		
							
								
								
									
										12
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								main.py
									
									
									
									
									
								
							| @@ -158,20 +158,14 @@ def handle_trade(trade): | ||||
|             # Check if time matches and current rate is above threshold | ||||
|             time_diff = (datetime.utcnow() - trade.open_date).total_seconds() / 60 | ||||
|             if time_diff > duration and current_rate > (1 + threshold) * trade.open_rate: | ||||
|  | ||||
|                 # Execute sell and update trade record | ||||
|                 order_id = api_wrapper.sell(trade.pair, current_rate, balance) | ||||
|                 trade.close_rate = current_rate | ||||
|                 trade.close_profit = current_profit | ||||
|                 trade.close_date = datetime.utcnow() | ||||
|                 trade.open_order_id = order_id | ||||
|  | ||||
|                 # Execute sell | ||||
|                 profit = trade.exec_sell_order(current_rate, balance) | ||||
|                 message = '*{}:* Selling [{}]({}) at rate `{:f} (profit: {}%)`'.format( | ||||
|                     trade.exchange.name, | ||||
|                     trade.pair.replace('_', '/'), | ||||
|                     api_wrapper.get_pair_detail_url(trade.pair), | ||||
|                     trade.close_rate, | ||||
|                     round(current_profit, 2) | ||||
|                     round(profit, 2) | ||||
|                 ) | ||||
|                 logger.info(message) | ||||
|                 TelegramHandler.send_msg(message) | ||||
|   | ||||
| @@ -5,10 +5,11 @@ from sqlalchemy.ext.declarative import declarative_base | ||||
| from sqlalchemy.orm import scoped_session, sessionmaker | ||||
| from sqlalchemy.types import Enum | ||||
|  | ||||
| from exchange import Exchange | ||||
| from exchange import Exchange, get_exchange_api | ||||
| from utils import get_conf | ||||
|  | ||||
| if get_conf().get('dry_run', False): | ||||
| conf = get_conf() | ||||
| if conf.get('dry_run', False): | ||||
|     db_handle = 'sqlite:///tradesv2.dry_run.sqlite' | ||||
| else: | ||||
|     db_handle = 'sqlite:///tradesv2.sqlite' | ||||
| @@ -45,4 +46,22 @@ class Trade(Base): | ||||
|             'closed' if not self.is_open else round((datetime.utcnow() - self.open_date).total_seconds() / 60, 2) | ||||
|         ) | ||||
|  | ||||
|     def exec_sell_order(self, rate, amount): | ||||
|         """ | ||||
|         Executes a sell for the given trade and updated the entity. | ||||
|         :param rate: rate to sell for | ||||
|         :param amount: amount to sell | ||||
|         :return: current profit as percentage | ||||
|         """ | ||||
|         profit = 100 * ((rate - self.open_rate) / self.open_rate) | ||||
|  | ||||
|         # Execute sell and update trade record | ||||
|         order_id = get_exchange_api(conf).sell(self.pair, rate, amount) | ||||
|         self.close_rate = rate | ||||
|         self.close_profit = profit | ||||
|         self.close_date = datetime.utcnow() | ||||
|         self.open_order_id = order_id | ||||
|         Session.flush() | ||||
|         return profit | ||||
|  | ||||
| Base.metadata.create_all(engine) | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import logging | ||||
| from datetime import timedelta | ||||
|  | ||||
| import arrow | ||||
| from sqlalchemy import and_ | ||||
| from telegram.error import NetworkError | ||||
| from telegram.ext import CommandHandler, Updater | ||||
| from telegram import ParseMode, Bot, Update | ||||
| @@ -57,7 +58,7 @@ class TelegramHandler(object): | ||||
|         trades = Trade.query.filter(Trade.is_open.is_(True)).all() | ||||
|         from main import get_instance | ||||
|         if not get_instance().is_alive(): | ||||
|             TelegramHandler.send_msg('*Status:* `trader stopped`', bot=bot) | ||||
|             TelegramHandler.send_msg('*Status:* `trader is not running`', bot=bot) | ||||
|         elif not trades: | ||||
|             TelegramHandler.send_msg('*Status:* `no active order`', bot=bot) | ||||
|         else: | ||||
| @@ -198,6 +199,54 @@ class TelegramHandler(object): | ||||
|         TelegramHandler.send_msg('*Order cancelled:* `{}`'.format(order_id), bot=bot) | ||||
|         logger.info('Order cancelled: (order_id: {})'.format(order_id)) | ||||
|  | ||||
|     @staticmethod | ||||
|     @authorized_only | ||||
|     def _forcesell(bot, update): | ||||
|         """ | ||||
|         Handler for /forcesell <id>. | ||||
|         Sells the given trade at current price | ||||
|         :param bot: telegram bot | ||||
|         :param update: message update | ||||
|         :return: None | ||||
|         """ | ||||
|         from main import get_instance | ||||
|         if not get_instance().is_alive(): | ||||
|             TelegramHandler.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: | ||||
|                 TelegramHandler.send_msg('There is no open trade with ID: `{}`'.format(trade_id)) | ||||
|                 return | ||||
|             # Get current rate | ||||
|             current_rate = api_wrapper.get_ticker(trade.pair)['bid'] | ||||
|             # Get available balance | ||||
|             currency = trade.pair.split('_')[1] | ||||
|             balance = api_wrapper.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('_', '/'), | ||||
|                 api_wrapper.get_pair_detail_url(trade.pair), | ||||
|                 trade.close_rate, | ||||
|                 round(profit, 2) | ||||
|             ) | ||||
|             logger.info(message) | ||||
|             TelegramHandler.send_msg(message) | ||||
|  | ||||
|         except ValueError: | ||||
|             TelegramHandler.send_msg('Invalid argument. Usage: `/forcesell <trade_id>`') | ||||
|             logger.warning('/forcesell: Invalid argument received') | ||||
|  | ||||
|     @staticmethod | ||||
|     @synchronized | ||||
|     def get_updater(conf): | ||||
| @@ -224,6 +273,7 @@ class TelegramHandler(object): | ||||
|             CommandHandler('start', TelegramHandler._start), | ||||
|             CommandHandler('stop', TelegramHandler._stop), | ||||
|             CommandHandler('cancel', TelegramHandler._cancel), | ||||
|             CommandHandler('forcesell', TelegramHandler._forcesell), | ||||
|         ] | ||||
|         for handle in handles: | ||||
|             TelegramHandler.get_updater(conf).dispatcher.add_handler(handle) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user