implement /forcesell command
This commit is contained in:
parent
3c0074520c
commit
3d5913d317
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)
|
||||
|
Loading…
Reference in New Issue
Block a user