def help(self, update, context): """Send a message when the command /help is issued.""" helptext = "<b>Information Command List</b>\n\n" helptext += ( "<b>/setcommands</b> - <i>add all commands to bot for easy access</i>\n" ) helptext += "<b>/margins</b> - <i>show margins for open trade</i>\n" helptext += "<b>/trades</b> - <i>show closed trades</i>\n" helptext += "<b>/stats</b> - <i>display stats for market</i>\n" # helptext += "<b>/showinfo</b> - <i>display bot(s) status</i>\n" # helptext += "<b>/showconfig</b> - <i>show config for exchange</i>\n\n" helptext += "<b>Interactive Command List</b>\n\n" helptext += "<b>/controlpanel</b> - <i>show interactive control buttons</i>\n" helptext += "<b>/cleandata</b> - <i>check and remove any bad Json files</i>\n" helptext += "<b>/addnew</b> - <i>start the requested pair</i>\n" # helptext += "<b>/pausebots</b> - <i>pause all or the selected bot</i>\n" # helptext += "<b>/resumebots</b> - <i>resume paused bots</i>\n" # helptext += "<b>/stopbots</b> - <i>stop all or the selected bots</i>\n" # helptext += "<b>/startbots</b> - <i>start all or the selected bots</i>\n" # helptext += "<b>/sell</b> - <i>sell market pair on next iteration</i>\n" # helptext += "<b>/buy</b> - <i>buy market pair on next iteration</i>\n\n" helptext += "<b>Market Scanner Commands</b>\n\n" helptext += "<b>/startscanner</b> - <i>start auto scan high volume markets and start bots</i>\n" helptext += "<b>/stopscanner</b> - <i>stop auto scan high volume markets</i>\n" helptext += "<b>/addexception</b> - <i>add pair to scanner exception list</i>\n" helptext += ( "<b>/removeexception</b> - <i>remove pair from scanner exception list</i>\n" ) mbot = Telegram(self.token, str(context._chat_id_and_data[0])) mbot.send(helptext, parsemode="HTML")
def trades(self, update, context): """List trades""" if not self._checkifallowed(context._user_id_and_data[0], update): return self.helper.read_data() output = "" for time in self.helper.data["trades"]: output = "" output = ( output + f"<b>{self.helper.data['trades'][time]['pair']}</b>\n{time}") output = ( output + f"\n<i>Sold at: {self.helper.data['trades'][time]['price']} Margin: {self.helper.data['trades'][time]['margin']}</i>\n" ) if output != "": mbot = Telegram(self.token, str(context._chat_id_and_data[0])) mbot.send(output, parsemode="HTML")
class PyCryptoBot(): def __init__(self, exchange='coinbasepro', filename='config.json'): args = parse_arguments() self.api_key = '' self.api_secret = '' self.api_passphrase = '' self.api_url = '' if args['config'] is not None: filename = args['config'] if args['exchange'] is not None: if args['exchange'] not in ['coinbasepro', 'binance', 'dummy']: raise TypeError('Invalid exchange: coinbasepro, binance') else: self.exchange = args['exchange'] else: self.exchange = exchange self.market = 'BTC-GBP' self.base_currency = 'BTC' self.quote_currency = 'GBP' self.granularity = 3600 self.is_live = 0 self.is_verbose = 0 self.save_graphs = 0 self.is_sim = 0 self.simstartdate = None self.simenddate = None self.sim_speed = 'fast' self.sell_upper_pcnt = None self.sell_lower_pcnt = None self.trailing_stop_loss = None self.sell_at_loss = 1 self.smart_switch = 1 self.telegram = False self.buypercent = 100 self.sellpercent = 100 self.last_action = None self._chat_client = None self.buymaxsize = None self.configbuilder = False self.sellatresistance = False self.autorestart = False self.disablebullonly = False self.disablebuynearhigh = False self.disablebuymacd = False self.disablebuyobv = False self.disablebuyelderray = False self.disablefailsafefibonaccilow = False self.disablefailsafelowerpcnt = False self.disableprofitbankupperpcnt = False self.disableprofitbankreversal = False self.disabletelegram = False self.disablelog = False self.disabletracker = False self.filelog = True self.logfile = args['logfile'] if args['logfile'] else 'pycryptobot.log' self.fileloglevel = 'DEBUG' self.consolelog = True self.consoleloglevel = 'INFO' self.ema1226_1h_cache = None self.ema1226_6h_cache = None self.sma50200_1h_cache = None if args['init']: # config builder cb = ConfigBuilder() cb.init() sys.exit() try: with open(filename) as config_file: config = json.load(config_file) if exchange not in config and 'binance' in config: self.exchange = 'binance' if self.exchange == 'coinbasepro' and 'coinbasepro' in config: coinbaseProConfigParser(self, config['coinbasepro'], args) elif self.exchange == 'binance' and 'binance' in config: binanceConfigParser(self, config['binance'], args) elif self.exchange == 'dummy' and 'dummy' in config: dummyConfigParser(self, config['dummy'], args) if not self.disabletelegram and 'telegram' in config and 'token' in config[ 'telegram'] and 'client_id' in config['telegram']: telegram = config['telegram'] self._chat_client = Telegram(telegram['token'], telegram['client_id']) self.telegram = True if 'logger' in config: loggerConfigParser(self, config['logger']) if self.disablelog: self.filelog = 0 self.fileloglevel = 'NOTSET' self.logfile == "pycryptobot.log" Logger.configure(filelog=self.filelog, logfile=self.logfile, fileloglevel=self.fileloglevel, consolelog=self.consolelog, consoleloglevel=self.consoleloglevel) except json.decoder.JSONDecodeError as err: sys.tracebacklimit = 0 raise ValueError('Invalid config.json: ' + str(err)) except IOError as err: sys.tracebacklimit = 0 raise ValueError('Invalid config.json: ' + str(err)) except ValueError as err: sys.tracebacklimit = 0 raise ValueError('Invalid config.json: ' + str(err)) def _isCurrencyValid(self, currency): if self.exchange == 'coinbasepro' or self.exchange == 'binance': p = re.compile(r"^[1-9A-Z]{2,5}$") return p.match(currency) return False def _isMarketValid(self, market): if self.exchange == 'coinbasepro': p = re.compile(r"^[1-9A-Z]{2,5}\-[1-9A-Z]{2,5}$") return p.match(market) elif self.exchange == 'binance': p = re.compile(r"^[A-Z0-9]{6,12}$") return p.match(market) return False def getLogFile(self): return self.logfile def getExchange(self): return self.exchange def getChatClient(self): return self._chat_client def getAPIKey(self): return self.api_key def getAPISecret(self): return self.api_secret def getAPIPassphrase(self): return self.api_passphrase def getAPIURL(self): return self.api_url def getBaseCurrency(self): return self.base_currency def getQuoteCurrency(self): return self.quote_currency def getMarket(self): return self.market def getGranularity(self) -> int: return self.granularity def getVersionFromREADME(self) -> str: try: count = 0 with open('README.md', 'r', encoding='utf8') as reader: line = reader.readline() while count < 5: line = reader.readline() if '# Python Crypto Bot' in line: line = line.replace('# Python Crypto Bot ', '') line = line.replace(' (pycryptobot)', '') return line.strip() count = count + 1 return 'v0.0.0' except Exception: return 'v0.0.0' def printGranularity(self) -> str: if self.exchange == 'binance': return to_binance_granularity(self.granularity) if self.exchange == 'coinbasepro': return str(self.granularity) if self.exchange == 'dummy': return str(self.granularity) raise TypeError('Unknown exchange "' + self.exchange + '"') def getBuyPercent(self): try: return int(self.buypercent) except Exception: return 100 def getSellPercent(self): try: return int(self.sellpercent) except Exception: return 100 def getBuyMaxSize(self): try: return float(self.buymaxsize) except Exception: return None def getHistoricalData(self, market, granularity: int, iso8601start='', iso8601end=''): if self.exchange == 'coinbasepro': api = CBPublicAPI() if iso8601start != '' and iso8601end == '': return api.getHistoricalData( market, to_coinbase_pro_granularity(granularity), iso8601start) elif iso8601start != '' and iso8601end != '': return api.getHistoricalData( market, to_coinbase_pro_granularity(granularity), iso8601start, iso8601end) else: return api.getHistoricalData( market, to_coinbase_pro_granularity(granularity)) elif self.exchange == 'binance': api = BPublicAPI() if iso8601start != '' and iso8601end != '': return api.getHistoricalData( market, to_binance_granularity(granularity), str( datetime.strptime( iso8601start, '%Y-%m-%dT%H:%M:%S.%f').strftime('%d %b, %Y')), str( datetime.strptime( iso8601end, '%Y-%m-%dT%H:%M:%S.%f').strftime('%d %b, %Y'))) else: return api.getHistoricalData( market, to_binance_granularity(granularity)) else: return pd.DataFrame() def getHistoricalDataChained(self, market, granularity: int, max_interations: int = 1) -> pd.DataFrame: df1 = self.getHistoricalData(market, self.getGranularity()) if max_interations == 1: return df1 def getPreviousDateRange(df: pd.DataFrame = None) -> tuple: end_date = df['date'].min() - timedelta(seconds=(granularity / 60)) new_start = df['date'].min() - timedelta(hours=300) return (str(new_start).replace(' ', 'T'), str(end_date).replace(' ', 'T')) iterations = 0 result_df = pd.DataFrame() while iterations < (max_interations - 1): start_date, end_date = getPreviousDateRange(df1) df2 = self.getHistoricalData(market, granularity, start_date, end_date) result_df = pd.concat([df2, df1]).drop_duplicates() df1 = result_df iterations = iterations + 1 if 'date' in result_df: result_df.sort_values(by=['date'], ascending=True, inplace=True) return result_df def getSmartSwitch(self): return self.smart_switch def is1hEMA1226Bull(self): try: if self.isSimulation() and isinstance(self.ema1226_1h_cache, pd.DataFrame): df_data = self.ema1226_1h_cache elif self.exchange == 'coinbasepro': api = CBPublicAPI() df_data = api.getHistoricalData(self.market, 3600) self.ema1226_1h_cache = df_data elif self.exchange == 'binance': api = BPublicAPI() df_data = api.getHistoricalData(self.market, '1h') self.ema1226_1h_cache = df_data else: return False ta = TechnicalAnalysis(df_data) if 'ema12' not in df_data: ta.addEMA(12) if 'ema26' not in df_data: ta.addEMA(26) df_last = ta.getDataFrame().copy().iloc[-1, :] df_last['bull'] = df_last['ema12'] > df_last['ema26'] return bool(df_last['bull']) except Exception: return False def is1hSMA50200Bull(self): try: if self.isSimulation() and isinstance(self.sma50200_1h_cache, pd.DataFrame): df_data = self.sma50200_1h_cache if self.exchange == 'coinbasepro': api = CBPublicAPI() df_data = api.getHistoricalData(self.market, 3600) self.sma50200_1h_cache = df_data elif self.exchange == 'binance': api = BPublicAPI() df_data = api.getHistoricalData(self.market, '1h') self.sma50200_1h_cache = df_data else: return False ta = TechnicalAnalysis(df_data) if 'sma50' not in df_data: ta.addSMA(50) if 'sma200' not in df_data: ta.addSMA(200) df_last = ta.getDataFrame().copy().iloc[-1, :] df_last['bull'] = df_last['sma50'] > df_last['sma200'] return bool(df_last['bull']) except Exception: return False def isCryptoRecession(self): try: if self.exchange == 'coinbasepro': api = CBPublicAPI() df_data = api.getHistoricalData(self.market, 86400) elif self.exchange == 'binance': api = BPublicAPI() df_data = api.getHistoricalData(self.market, '1d') else: return False # if there is an API issue, default to False to avoid hard sells if len(df_data) <= 200: return False # if there is insufficient data, default to False to avoid hard sells ta = TechnicalAnalysis(df_data) ta.addSMA(50) ta.addSMA(200) df_last = ta.getDataFrame().copy().iloc[-1, :] df_last['crypto_recession'] = df_last['sma50'] < df_last['sma200'] return bool(df_last['crypto_recession']) except Exception: return False def is6hEMA1226Bull(self): try: if isinstance(self.ema1226_6h_cache, pd.DataFrame): df_data = self.ema1226_6h_cache elif self.exchange == 'coinbasepro': api = CBPublicAPI() df_data = api.getHistoricalData(self.market, 21600) self.ema1226_6h_cache = df_data elif self.exchange == 'binance': api = BPublicAPI() df_data = api.getHistoricalData self.ema1226_6h_cache = df_data(self.market, '6h') else: return False ta = TechnicalAnalysis(df_data) if 'ema12' not in df_data: ta.addEMA(12) if 'ema26' not in df_data: ta.addEMA(26) df_last = ta.getDataFrame().copy().iloc[-1, :] df_last['bull'] = df_last['ema12'] > df_last['ema26'] return bool(df_last['bull']) except Exception: return False def is6hSMA50200Bull(self): try: if self.exchange == 'coinbasepro': api = CBPublicAPI() df_data = api.getHistoricalData(self.market, 21600) elif self.exchange == 'binance': api = BPublicAPI() df_data = api.getHistoricalData(self.market, '6h') else: return False ta = TechnicalAnalysis(df_data) ta.addSMA(50) ta.addSMA(200) df_last = ta.getDataFrame().copy().iloc[-1, :] df_last['bull'] = df_last['sma50'] > df_last['sma200'] return bool(df_last['bull']) except Exception: return False def getTicker(self, market): if self.exchange == 'coinbasepro': api = CBPublicAPI() return api.getTicker(market) elif self.exchange == 'binance': api = BPublicAPI() return api.getTicker(market) else: return None def getTime(self): if self.exchange == 'coinbasepro': return CBPublicAPI().getTime() elif self.exchange == 'binance': try: return BPublicAPI().getTime() except ReadTimeoutError: return '' else: return '' def isLive(self) -> bool: return self.is_live == 1 def isVerbose(self) -> bool: return self.is_verbose == 1 def shouldSaveGraphs(self) -> bool: return self.save_graphs == 1 def isSimulation(self) -> bool: return self.is_sim == 1 def simuluationSpeed(self): return self.sim_speed def sellUpperPcnt(self): return self.sell_upper_pcnt def sellLowerPcnt(self): return self.sell_lower_pcnt def trailingStopLoss(self): return self.trailing_stop_loss def allowSellAtLoss(self) -> bool: return self.sell_at_loss == 1 def showConfigBuilder(self) -> bool: return self.configbuilder def sellAtResistance(self) -> bool: return self.sellatresistance def autoRestart(self) -> bool: return self.autorestart def getLastAction(self): return self.last_action def disableBullOnly(self) -> bool: return self.disablebullonly def disableBuyNearHigh(self) -> bool: return self.disablebuynearhigh def disableBuyMACD(self) -> bool: return self.disablebuymacd def disableBuyOBV(self) -> bool: return self.disablebuyobv def disableBuyElderRay(self) -> bool: return self.disablebuyelderray def disableFailsafeFibonacciLow(self) -> bool: return self.disablefailsafefibonaccilow def disableFailsafeLowerPcnt(self) -> bool: return self.disablefailsafelowerpcnt def disableProfitbankUpperPcnt(self) -> bool: return self.disableprofitbankupperpcnt def disableProfitbankReversal(self) -> bool: return self.disableprofitbankreversal def disableLog(self) -> bool: return self.disablelog def disableTracker(self) -> bool: return self.disabletracker def setGranularity(self, granularity: int): if granularity in [60, 300, 900, 3600, 21600, 86400]: self.granularity = granularity def compare(self, val1, val2, label='', precision=2): if val1 > val2: if label == '': return truncate(val1, precision) + ' > ' + truncate( val2, precision) else: return label + ': ' + truncate( val1, precision) + ' > ' + truncate(val2, precision) if val1 < val2: if label == '': return truncate(val1, precision) + ' < ' + truncate( val2, precision) else: return label + ': ' + truncate( val1, precision) + ' < ' + truncate(val2, precision) else: if label == '': return truncate(val1, precision) + ' = ' + truncate( val2, precision) else: return label + ': ' + truncate( val1, precision) + ' = ' + truncate(val2, precision) def getLastBuy(self) -> dict: """Retrieves the last exchange buy order and returns a dictionary""" try: if self.exchange == 'coinbasepro': api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL()) orders = api.getOrders(self.getMarket(), '', 'done') if len(orders) == 0: return None last_order = orders.tail(1) if last_order['action'].values[0] != 'buy': return None return { 'side': 'buy', 'market': self.getMarket(), 'size': float(last_order['size']), 'filled': float(last_order['filled']), 'price': float(last_order['price']), 'fee': float(last_order['fees']), 'date': str( pd.DatetimeIndex( pd.to_datetime( last_order['created_at']).dt.strftime( '%Y-%m-%dT%H:%M:%S.%Z'))[0]) } elif self.exchange == 'binance': api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL()) orders = api.getOrders(self.getMarket()) if len(orders) == 0: return None last_order = orders.tail(1) if last_order['action'].values[0] != 'buy': return None return { 'side': 'buy', 'market': self.getMarket(), 'size': float(last_order['size']), 'filled': float(last_order['filled']), 'price': float(last_order['price']), 'fees': float(last_order['size'] * 0.001), 'date': str( pd.DatetimeIndex( pd.to_datetime( last_order['created_at']).dt.strftime( '%Y-%m-%dT%H:%M:%S.%Z'))[0]) } else: return None except Exception: return None def getTakerFee(self): if self.isSimulation() is True and self.exchange == 'coinbasepro': return 0.005 # default lowest fee tier elif self.isSimulation() is True and self.exchange == 'binance': return 0.001 # default lowest fee tier elif self.exchange == 'coinbasepro': api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL()) return api.getTakerFee() elif self.exchange == 'binance': api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL()) return api.getTakerFee() else: return 0.005 def getMakerFee(self): if self.exchange == 'coinbasepro': api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL()) return api.getMakerFee() elif self.exchange == 'binance': api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL()) # return api.getMakerFee() return 0.005 else: return 0.005 def marketBuy(self, market, quote_currency, buy_percent=100): if self.is_live == 1: if isinstance(buy_percent, int): if buy_percent > 0 and buy_percent < 100: quote_currency = (buy_percent / 100) * quote_currency if self.exchange == 'coinbasepro': api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL()) return api.marketBuy(market, float(truncate(quote_currency, 2))) elif self.exchange == 'binance': api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL()) return api.marketBuy(market, quote_currency) else: return None def marketSell(self, market, base_currency, sell_percent=100): if self.is_live == 1: if isinstance(sell_percent, int): if sell_percent > 0 and sell_percent < 100: base_currency = (sell_percent / 100) * base_currency if self.exchange == 'coinbasepro': api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL()) return api.marketSell(market, base_currency) elif self.exchange == 'binance': api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL()) return api.marketSell(market, base_currency) else: return None def setMarket(self, market): if self.exchange == 'binance': self.market, self.base_currency, self.quote_currency = binanceParseMarket( market) elif self.exchange == 'coinbasepro': self.market, self.base_currency, self.quote_currency = coinbaseProParseMarket( market) return (self.market, self.base_currency, self.quote_currency) def setLive(self, flag): if isinstance(flag, int) and flag in [0, 1]: self.is_live = flag def setNoSellAtLoss(self, flag): if isinstance(flag, int) and flag in [0, 1]: self.sell_at_loss = flag def startApp(self, account, last_action='', banner=True): if banner: Logger.info( '--------------------------------------------------------------------------------' ) Logger.info( '| Python Crypto Bot |' ) Logger.info( '--------------------------------------------------------------------------------' ) txt = ' Release : ' + self.getVersionFromREADME() Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') Logger.info( '-----------------------------------------------------------------------------' ) if self.isVerbose(): txt = ' Market : ' + self.getMarket() Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Granularity : ' + str( self.getGranularity()) + ' seconds' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') Logger.info( '-----------------------------------------------------------------------------' ) if self.isLive(): txt = ' Bot Mode : LIVE - live trades using your funds!' else: txt = ' Bot Mode : TEST - test trades using dummy funds :)' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Bot Started : ' + str(datetime.now()) Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') Logger.info( '================================================================================' ) if self.sellUpperPcnt() != None: txt = ' Sell Upper : ' + str( self.sellUpperPcnt()) + '%' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') if self.sellLowerPcnt() != None: txt = ' Sell Lower : ' + str( self.sellLowerPcnt()) + '%' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') if self.trailingStopLoss() != None: txt = ' Trailing Stop Loss : ' + str( self.trailingStopLoss()) + '%' Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Sell At Loss : ' + str( self.allowSellAtLoss()) + ' --sellatloss ' + str( self.allowSellAtLoss()) Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Sell At Resistance : ' + str( self.sellAtResistance()) + ' --sellatresistance' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Trade Bull Only : ' + str( not self.disableBullOnly()) + ' --disablebullonly' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Buy Near High : ' + str( not self.disableBuyNearHigh()) + ' --disablebuynearhigh' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Use Buy MACD : ' + str( not self.disableBuyMACD()) + ' --disablebuymacd' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Use Buy OBV : ' + str( not self.disableBuyOBV()) + ' --disablebuyobv' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Use Buy Elder-Ray : ' + str( not self.disableBuyElderRay()) + ' --disablebuyelderray' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Sell Fibonacci Low : ' + str( not self.disableFailsafeFibonacciLow() ) + ' --disablefailsafefibonaccilow' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') if self.sellLowerPcnt() != None: txt = ' Sell Lower Pcnt : ' + str( not self.disableFailsafeLowerPcnt() ) + ' --disablefailsafelowerpcnt' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') if self.sellUpperPcnt() != None: txt = ' Sell Upper Pcnt : ' + str( not self.disableFailsafeLowerPcnt() ) + ' --disableprofitbankupperpcnt' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Candlestick Reversal : ' + str( not self.disableProfitbankReversal() ) + ' --disableprofitbankreversal' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Telegram : ' + str( not self.disabletelegram) + ' --disabletelegram' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Log : ' + str( not self.disableLog()) + ' --disablelog' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Tracker : ' + str( not self.disableTracker()) + ' --disabletracker' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Auto restart Bot : ' + str( self.autoRestart()) + ' --autorestart' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') if self.getBuyMaxSize(): txt = ' Max Buy Size : ' + str( self.getBuyMaxSize()) + ' --buymaxsize <size>' Logger.info('| ' + txt + (' ' * (75 - len(txt))) + ' | ') Logger.info( '================================================================================' ) # run the first job immediately after starting if self.isSimulation(): if self.simuluationSpeed() in ['fast-sample', 'slow-sample']: tradingData = pd.DataFrame() attempts = 0 if self.simstartdate is not None: date = self.simstartdate.split('-') startDate = datetime(int(date[0]), int(date[1]), int(date[2])) endDate = startDate + timedelta( minutes=(self.getGranularity() / 60) * 300) while len(tradingData) != 300 and attempts < 10: tradingData = self.getHistoricalData( self.getMarket(), self.getGranularity(), startDate.isoformat(timespec='milliseconds')) attempts += 1 elif self.simenddate is not None: if self.simenddate == 'now': endDate = datetime.now() else: date = self.simenddate.split('-') endDate = datetime(int(date[0]), int(date[1]), int(date[2])) startDate = endDate - timedelta( minutes=(self.getGranularity() / 60) * 300) while len(tradingData) != 300 and attempts < 10: tradingData = self.getHistoricalData( self.getMarket(), self.getGranularity(), startDate.isoformat(timespec='milliseconds')) attempts += 1 else: while len(tradingData) != 300 and attempts < 10: endDate = datetime.now() - timedelta( hours=random.randint(0, 8760 * 3)) # 3 years in hours startDate = endDate - timedelta( minutes=(self.getGranularity() / 60) * 300) tradingData = self.getHistoricalData( self.getMarket(), self.getGranularity(), startDate.isoformat(timespec='milliseconds')) attempts += 1 if len(tradingData) != 300: raise Exception( 'Unable to retrieve 300 random sets of data between ' + str(startDate) + ' and ' + str(endDate) + ' in ' + str(attempts) + ' attempts.') if banner: startDate = str(startDate.isoformat()) endDate = str(endDate.isoformat()) txt = ' Sampling start : ' + str(startDate) Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Sampling end : ' + str(endDate) Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ') if self.simstartdate != None: txt = ' WARNING: Using less than 300 intervals' Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ') txt = ' Interval size : ' + str(len(tradingData)) Logger.info(' | ' + txt + (' ' * (75 - len(txt))) + ' | ') Logger.info( '================================================================================' ) else: tradingData = self.getHistoricalData(self.getMarket(), self.getGranularity()) return tradingData def notifyTelegram(self, msg: str) -> None: """ Send a given message to preconfigured Telegram. If the telegram isn't enabled, e.g. via `--disabletelegram`, this method does nothing and returns immediately. """ if self.disabletelegram or not self.telegram: return assert self._chat_client is not None self._chat_client.send(msg)