def balance_thread(): if not os.path.isfile("mqtt_config.txt"): raise Exception( "MQTT is not configured. " "Create mqtt_config.txt with first line mqtt server IP address and " "second line with user name and" "third line with your password and" "forth line with your topic for account balance.") with open("mqtt_config.txt") as fp: ip = fp.readline().strip() user = fp.readline().strip() password = fp.readline().strip() topic = fp.readline().strip() while True: balance = exchange.get_balance() publish.single(topic, payload="{0}".format( sum([coin['usdtValue'] for coin in balance])), qos=0, retain=True, hostname=ip, port=1883, client_id="", keepalive=60, will=None, auth={ 'username': user, 'password': password }, tls=None) time.sleep(20)
def balance_thread(): if not os.path.isfile("mqtt_config.txt"): raise Exception("MQTT is not configured. " "Create mqtt_config.txt with first line mqtt server IP address and " "second line with user name and" "third line with your password and" "forth line with your topic for account balance.") with open("mqtt_config.txt") as fp: ip = fp.readline().strip() user = fp.readline().strip() password = fp.readline().strip() topic = fp.readline().strip() while True: balance = exchange.get_balance() publish.single(topic, payload="{0}".format(sum([coin['usdtValue'] for coin in balance])), qos=0, retain=True, hostname=ip, port=1883, client_id="", keepalive=60, will=None, auth={'username': user, 'password': password}, tls=None) time.sleep(20)
def orders_change_thread(): orders = {} pushover = Pushover() while True: completed = "" pending = "" new = "" new_orders = exchange.get_open_orders() balance = exchange.get_balance() if orders != new_orders: for coin in orders: for o in orders[coin]: if coin not in new_orders: completed += "{0} {1} amount: {2}, total: {3}\n".format(o['type'].capitalize(), coin, o['amount'], o['total']) else: for new_o in new_orders[coin]: if new_o != o: completed += "{0} {1} amount: {2}, total: {3}\n".format(o['type'].capitalize(), coin, o['amount'], o['total']) for coin in new_orders: for o in new_orders[coin]: if coin not in orders: new += "{0} {1} amount: {2}, total: {3}\n".format(o['type'].capitalize(), coin, o['amount'], o['total']) else: for old_o in orders[coin]: if old_o != o: new += "{0} {1} amount: {2}, total: {3}\n".format(o['type'].capitalize(), coin, o['amount'], o['total']) for coin in new_orders: for o in new_orders[coin]: pending += "{0} {1} amount: {2}, total: {3}\n".format(o['type'].capitalize(), coin, o['amount'], o['total']) message = "" if completed != "": message += "Completed or canceled orders:\n" message += completed message += "\n" if new != "": message += "New orders:\n" message += new message += "\n" if pending != "": message += "Pending orders:\n" message += pending message += "\n" if message != "": message += "Total balance: {0:.2f} USDT".format(sum([coin['usdtValue'] for coin in balance])) print("---------------------------") print(datetime.datetime.now()) print(message) pushover.send(message) orders = new_orders time.sleep(10)
def check_update(self, force=False, diff_check=True): now = dt.datetime.now() time_diff = now - self.last_update lower_bound = self.interval * self.leniency #e.g. 5min*0.99=4min,57sec if time_diff > lower_bound or force: if diff_check: old_balances = dict(self.balances) old_balances_by_exchange_total = dict( self.balances_by_exchange_total) old_balances_by_exchange_free = dict( self.balances_by_exchange_free) for ex in exchange_objs: m = ex.load_markets(True) #Force reload of markets self.balances_by_exchange_total[ex] = exchange.get_balance( ex, 'total') self.balances_by_exchange_free[ex] = exchange.get_balance( ex, 'free') #Be lazy and just call fetch_balance on every exchange again #TODO: be less lazy self.balances = exchange.get_balances(self.exchange_objs) # Balance diffs if diff_check: bals_diff = dict_diff(self.balances, old_balances) bal_total_diff = {} bal_free_diff = {} for ex in exchange_objs: bal_total_diff[ex] = dict_diff( self.balances_by_exchange_total[ex], old_balances_by_exchange_total[ex]) bal_free_diff[ex] = dict_diff( self.balances_by_exchange_free[ex], old_balances_by_exchange_free[ex]) print('Balance Diffs (New-Old):') print('\nTotals: \n----------') pprint(bals_diff) print('\nTotal by exchange: \n----------') pprint(bal_total_diff) print('\nFree bals by exchange: \n ----------') pprint(bal_free_diff) print("Balances updated") self.last_updated = now
def create_trade(stake_amount: float, _exchange: exchange.Exchange) -> 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 :param _exchange: exchange to use """ logger.info('Creating new trade with stake_amount: %f ...', stake_amount) whitelist = _CONF[_exchange.name.lower()]['pair_whitelist'] # Check if btc_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 trades = Trade.query.filter(Trade.is_open.is_(True)).all() latest_trade = Trade.query.filter(Trade.is_open.is_(False)).order_by(Trade.id.desc()).first() if latest_trade: trades.append(latest_trade) for trade in trades: 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 = exchange.get_ticker(pair)['ask'] 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.name, pair.replace('_', '/'), exchange.get_pair_detail_url(pair), open_rate ) logger.info(message) telegram.send_msg(message) return Trade(pair=pair, btc_amount=stake_amount, open_rate=open_rate, open_date=datetime.utcnow(), amount=amount, exchange=_exchange, open_order_id=order_id, is_open=True)
def __init__(self, exchange_objs, coin_to_exchange, start, interval, leniency=0.99, verbose=True): #exchange_objs - ccxt exchange objects #coin_to_exchange - dict of which exchange to use for each coin {coin : exchange_obj} #interval - update frequency to fetch new data, typically not the same as the strat interval! #start - time at which the script was started (if not <10s from now, a reboot occurred) #leniency - float in range (0,1] that is the "wiggle room" for any time related activity #e.g. 0.99 leniency --> 14 minutes over 24h, 3s over 5min. self.exchange_objs = exchange_objs self.coin_to_exchange = dict( coin_to_exchange ) #make copy as we might make changes and this is a global var self.balances = exchange.get_balances( exchange_objs) # {coin_id : val_base} self.balances_by_exchange_total = { } # {exchange_obj : {coin_id : val_base}} self.balances_by_exchange_free = {} # ditto for ex in exchange_objs: self.balances_by_exchange_total[ex] = exchange.get_balance( ex, 'total') self.balances_by_exchange_free[ex] = exchange.get_balance( ex, 'free') self.stop_loss = {} # {coin_id : price_USD} self.avg_price = {} # {coin_id : price_USD} self.now = dt.datetime.now() self.start = start self.interval = interval self.leniency = leniency self.last_update = dt.datetime.now() self.check_update(force=True) if self.now - start > dt.timedelta(seconds=10): #Start was more than 10 seconds ago, probably a reboot. #TODO: HANDLE REBOOTS raise NotImplementedError( 'Reboots are not handled yet. Start time is more than 10s ago.' )
def get_forcesell(self, trade): # 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)) return message
def execute_sell(trade: Trade, current_rate: float) -> None: """ Executes a sell for the given trade and current rate :param trade: Trade instance :param current_rate: current rate :return: None """ # Get available balance currency = trade.pair.split('_')[1] balance = exchange.get_balance(currency) profit = trade.exec_sell_order(current_rate, balance) message = '*{}:* Make It Rain!!!! with [{}]({}) for `{: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) telegram.send_msg(message)
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 execute_sell(trade: Trade, current_rate: float) -> None: """ Executes a sell for the given trade and current rate :param trade: Trade instance :param current_rate: current rate :return: None """ # Get available balance currency = trade.pair.split('_')[1] balance = exchange.get_balance(currency) whitelist = _CONF[trade.exchange.name.lower()]['pair_whitelist'] profit = trade.exec_sell_order(current_rate, balance) whitelist.append(trade.pair) 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) telegram.send_msg(message)
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 orders_change_thread(): orders = {} pushover = Pushover() while True: completed = "" pending = "" new = "" new_orders = exchange.get_open_orders() balance = exchange.get_balance() if orders != new_orders: for coin in orders: for o in orders[coin]: if coin not in new_orders: completed += "{0} {1} amount: {2}, total: {3}\n".format( o['type'].capitalize(), coin, o['amount'], o['total']) else: for new_o in new_orders[coin]: if new_o != o: completed += "{0} {1} amount: {2}, total: {3}\n".format( o['type'].capitalize(), coin, o['amount'], o['total']) for coin in new_orders: for o in new_orders[coin]: if coin not in orders: new += "{0} {1} amount: {2}, total: {3}\n".format( o['type'].capitalize(), coin, o['amount'], o['total']) else: for old_o in orders[coin]: if old_o != o: new += "{0} {1} amount: {2}, total: {3}\n".format( o['type'].capitalize(), coin, o['amount'], o['total']) for coin in new_orders: for o in new_orders[coin]: pending += "{0} {1} amount: {2}, total: {3}\n".format( o['type'].capitalize(), coin, o['amount'], o['total']) message = "" if completed != "": message += "Completed or canceled orders:\n" message += completed message += "\n" if new != "": message += "New orders:\n" message += new message += "\n" if pending != "": message += "Pending orders:\n" message += pending message += "\n" if message != "": message += "Total balance: {0:.2f} USDT".format( sum([coin['usdtValue'] for coin in balance])) print("---------------------------") print(datetime.datetime.now()) print(message) pushover.send(message) orders = new_orders time.sleep(10)