def checkMarketStatus(self, currency, data=None): if data is None: data = self.datastore[currency] market = CoinCalc.getInstance().get_market(currency) if market: traderTA = Trader(market) self.cs = traderTA.get_candlesticks(self.timeframe, self.framesize) ath = 0 for v in self.cs["high"]: if v > ath: ath = v atl = 9999999 for v in self.cs["low"]: if v < atl: atl = v ret = { "price": { "count": 0, "last": self.cs["closed"][-1], "open": self.cs["open"][-1], "HIGH": ath, "LOW": atl, "time": self.cs["time"][-1], } } for indicator in self.indicators: if indicator == "macd": macd = MACD(self.cs) ret["macd"] = macd.get_analysis(data) elif indicator == "bbands": bb = BBands(self.cs, timeperiod=20, nbdevup=2, nbdevdn=2) ret["bbands"] = bb.get_analysis(data) return ret
def market_tadata(worker_id): global influxDb while True: try: res = ExchangeDataHandler().getInstance().getRedisDb().blpop( "ta_markets") market = res[1].decode("utf-8") received_ts = time.strftime("%c") for framesize in frame_sizes.split(" "): starttime = time.time() traderTA = Trader(market) cs = traderTA.get_candlesticks("24h", framesize) traderTA.get_indicators() endtime = time.time() diftime = endtime - starttime #print("TA on {} with {} framesize completed in {}".format(market,framesize,diftime)) for i in range(0, traderTA.get_indicator_size()): res = traderTA.get_indicator_index(i) influxDb.bulkAddTA("bittrex", traderTA.market, framesize, res, diftime) except Exception as ex: print("market_tadata exception thrown: {}".format(ex))
class TradeBot(object): OVERBOUGHT = 100 OVERSOLD = 200 #def __init__(self, market,budget, tradelimit, candlestick = "5m",timeframe = "24h", name = None, config = {} ): def __init__(self, name, config): self.cycles = 0 self.config = config self.name = name self.budget = config.get("budget", 0) self.initial_budget = self.budget self.tradelimit = config.get("tradelimit", 0) self.market = config.get("market", None) self.candlesize = config.get("candlesize", "1h") self.timeframe = config.get("timeframe", "1d") self.basesize = config.get("basesize", "1m") if not self.market: raise Exception( "missing required fields market: {}, budget: {}, tradelimit: {}" .format(self.market, self.budget, self.tradelimit)) if "usdt" in self.market.lower(): self.scale = config.get("scale", "2") else: self.scale = config.get("scale", "8") self.tcpsock = None # move this functionality to wallet class self.growth_target = config.get("growthtarget", 2) self.stop_loss = config.get("stoploss", 3) self.signal = None self.results = {} #dataprovider for candlestick data self.trader = Trader(market=self.market) #candlestick data self.csdata = None #manage indicators self.analyzer = None #manage orders self.ordermanager = None #keep track of latest indicator and bot signals self.signal_history = {} self.all_signals = [] self.log = logging.getLogger('crypto') # debug messages passed to bot client self.debug = [] #aggregate bot data for bot client self.data_provider = BotDataProvider(self) #enable backtesting... self.backtest = config.get("backtest", False) if "backtest_start_time" in config: ts = config["backtest_start_time"] else: ofs = config.get("backtest_start_ofs", 259200) ts = time.time() - ofs ts = ts - (ts % 3600) - config.get("run_offset", 0) self.backtest_tick = ts self.backtest_startprice = None self.backtest_endprice = 0 self.run_interval = config.get("run_interval", 300) if self.backtest: random.seed() rid = random.randint(100, 70000) self.name = "{}-{}".format(name, rid) def createSocket(self, ip="127.0.0.1", port): self.tcpsock = TcpSock(ip, port, self) self.tcpsock.start() def stopBackTest(self): self.backtest = False self.log.info("backtest completed") def marketRate(self, index=1): return self.analyzer.last("closed", index) def getOrderManager(self): return self.ordermanager def setOrderManager(self, om): self.ordermanager = om self.ordermanager.setBot(self) self.log.info("initializing order manager") self.ordermanager.startOrderMonitor(self.config.get( "orderrefresh", 60)) def getSignal(self): return self.signal def checkSignal(self, name, signal, timepassed): checktime = time.time() - timepassed if name in self.signal_history and self.signal_history[name][ "time"] > checktime: self.debug.append("checksignal {} triggered".format(name)) return self.signal_history[name]["strength"] return None def pushSignal(self, name, signal, strength, minor=False): if strength is not None: sig = { "name": self.getName(), "signal": signal, "rate": self.marketRate(), "cstime": self.analyzer.last("time"), "time": time.time(), "strength": strength, "count": 1 } if not minor: if self.signal and self.signal["name"] == sig[ "name"] and self.signal["cstime"] == sig["cstime"]: self.signal["count"] += 1 else: self.signal = sig if name in self.signal_history and self.signal_history[name][ "cstime"] == sig["cstime"]: self.signal_history[name]["count"] += 1 else: self.signal_history[name] = sig if not minor: self.all_signals.append(sig) def debug_reset(self): self.debug = [] def append_debug_message(self, msg): self.debug.append(msg) def get_debug_messages(self): return self.debug def process(self): res = None if self.getSignal(): res = self.getOrderManager().processSignal() self.getOrderManager().checkStops() self.cycles += 1 return res def candleColor(self, idx): if self.csdata['closed'][idx] >= self.csdata['open'][idx]: return 'green' else: return 'red' def candle(self, idx): return { "date": self.csdata["time"][idx], "open": self.csdata["open"][idx], "high": self.csdata["high"][idx], "low": self.csdata["low"][idx], "close": self.csdata["closed"][idx], "volume": self.csdata["volume"][idx], "basevolume": self.csdata["basevolume"][idx] } def refreshCandlesticks(self, csdata=None): # redo backtest logic.... if self.backtest: bt_time = "{}s".format(int(self.backtest_tick)) self.csdata = self.trader.get_candlesticks(self.timeframe, self.candlesize, dateOffset=bt_time, base_size=self.basesize) self.backtest_endprice = self.csdata["closed"][-1] if self.backtest_startprice is None: self.backtest_startprice = self.csdata["closed"][-1] self.backtest_tick += self.run_interval if self.backtest_tick > time.time(): self.log.info("backtest complete") self.backtest_tick = time.time() else: if csdata == None: self.csdata = self.trader.get_candlesticks( self.timeframe, size=self.candlesize, base_size=self.basesize) else: self.csdata = csdata self.analyzer = Analyzer(self.csdata) self.signal = None return self.analyzer def getAnalyzer(): return self.analyzer def getMarket(self): return self.market def getName(self): return self.name def getIndicators(self): return self.indicators def dataProvider(self): return self.data_provider def info(self): return { "name": self.name, "cycle": self.cycles, "signal": self.signal, "last": self.marketRate(), "time": self.analyzer.last("time"), "servertime": time.strftime("%c"), "config": self.config }
class Bot(object): def __init__(self, name, config, settings=None): self.log = logging.getLogger('crypto') self.config = config self.name = name # self.budget = config.get("budget",0) # self.initial_budget = self.budget # self.tradelimit = config.get("tradelimit",0) self.market = config.get("market", None) self.exchange = config.get("exchange", "bittrex") self.candlesize = config.get("candlesize", "5m") self.timeframe = config.get("timeframe", "3d") self.basesize = config.get("basesize", "1m") self.stopped = False if not self.market: raise Exception("missing required fields market: {}".format( self.market)) if "usdt" in self.market.lower(): self.scale = config.get("scale", 2) else: self.scale = config.get("scale", 8) # sync wallet with database ? self.syncWallet = config.get("syncWallet", False) #candlestick data self.csdata = None self.market_summary = None self.last = None self.scrapeDate = None self.startDate = None #dataprovider for candlestick data self.trader = Trader(market=self.market, exchange=self.exchange) #manage indicators self.analyzer = None #tcp socket self.tcpsock = None # signal details self.history = [] # bot signals self.signals = None #cached api results self.apiInfo = {} #bot settings self.defaults = None self.setDefaults() self.settings = self.updateSettings(settings) #threadHandler self.thread = None self.botSleep = 15 self.ticks = 0 self.eticks = 0 self.rticks = 0 self.refresh_high = None self.refresh_low = None self.candle_remaining = None wname = "sim:{}:{}".format(self.name, self.market) self.simwallet = TradeWallet({ 'market': self.market, 'name': wname, 'sync': False, 'scale': self.scale }) wname = "{}:{}".format(self.name, self.market) self.wallet = TradeWallet({ 'market': self.market, 'name': wname, 'mode': 'live', 'sync': self.syncWallet, 'scale': self.scale }) if self.syncWallet: self.wallet.load() self.wallet.notify("Traderbot {}: {} started".format( self.name, self.market)) def configure(self, config): self.config = { "market": "", "candlesize": "5m", "budget": 0.01, "maxtrades": 5, "target": 0.05, "stop": 0.025, "notify": "" } self.config = {**self.config, **config} def setDefaults(self): self.defaults = { "rsi.buy": 35, "rsi.sell": 65, "baseMinDistance": 0.04, "baseMultiplier": 10, "short.sma.period": 50, "long.sma.period": 200, "sma.bear.score": -25, "sma.bull.score": 5, "death.cross": -100, "golden.cross": 20, "dband.top": -15, "dband.bottom": 15, "bband.below": 5, "bband.above": -15, "bband.enter.bottom": 10, } def updateSettings(self, override=None): if override != None: self.settings = {**self.defaults, **override} else: self.settings = self.defaults return self.settings def score(self, score, csdataIndex, message): self.history.append({ 'candle': self.csdata['time'][csdataIndex], "score": score, "message": message }) return score def getInfo(self, query=None): if query in self.apiInfo: return self.apiInfo[query] elif query == "stop": self.stopped = True return json.dumps({"message": "bot stopped"}) def getSignals(self, idx): return {'signal': None, 'score': 0, 'messages': self.history} def buildOutput(self): self.apiInfo["help"] = json.dumps({"message": "no help here buddy"}) def processRunner(self): while not self.stopped: try: self.process() self.ticks += 1 except Exception as ex: print("Error: {}".format(ex)) self.eticks += 1 #raise ex # print(".",end=" ") time.sleep(self.botSleep) def start(self): self.startDate = datetime.datetime.utcnow().strftime( '%Y-%m-%dT%H:%M:%S') self.thread = Thread(target=self.processRunner) self.thread.start() def stop(self): self.thread.join() def isStopped(self): return self.stopped def process(self, options={}): return None def refresh(self, scrape=False): # print("market={},exchange={}".format(self.market, self.exchange)) scraper = Scraper({'market': self.market, 'exchange': self.exchange}) self.candle_remaining = self.trader.getCandleRemaining() if self.candle_remaining is None: csdata = None if scrape: try: if self.candlesize == "1d" or self.candlesize == "1h": cs = self.candlesize else: cs = "1m" # print('scraping:{}'.format(cs)) csdata = scraper.cc_scrapeCandle(cs) self.scrapeDate = datetime.datetime.utcnow().strftime( '%Y-%m-%dT%H:%M:%S') self.rticks += 1 except Exception as ex: print(ex) if self.candlesize not in ("1m", "1d", "1h"): csdata = None self.loadCandlesticks(csdata) try: if self.exchange == "bittrex": self.market_summary = Bittrex().public_get_market_summary( self.market).data["result"][0] else: last = scraper.cc_lastprice() self.market_summary = {"Last": last, "Ask": 0, "Bid": 0} except Exception as ex: self.market_summary = { "Last": self.csdata["closed"][-1], "Ask": 0, "Bid": 0 } self.last = self.market_summary['Last'] self.csdata['closed'][-1] = self.last if self.candle_remaining is not None: if self.last > self.refresh_high: self.refresh_high == self.last if self.last < self.refresh_low: self.refresh_low = self.last else: self.refresh_high = self.csdata["high"][-1] self.refresh_low = self.csdata["low"][-1] #self.candle_remaining = self.trader.candle_remaining self.csdata["high"][-1] = self.refresh_high self.csdata["low"][-1] = self.refresh_low self.calculate_ta() def lastidx(self): return len(self.csdata['closed']) - 1 def calculate_ta(self): self.tadata = {} def createSocket(self, ip="127.0.0.1", port=9500): self.tcpsock = TcpSock(ip, port, self) self.tcpsock.start() def closeSocket(self): self.tcpsock.close() def candleColor(self, idx): if self.csdata['closed'][idx] >= self.csdata['open'][idx]: return 'green' else: return 'red' def candle(self, idx, ta=None): candle = { "date": self.csdata["time"][idx], "open": self.csdata["open"][idx], "high": self.csdata["high"][idx], "low": self.csdata["low"][idx], "close": self.csdata["closed"][idx], "volume": self.csdata["volume"][idx], "basevolume": self.csdata["basevolume"][idx] } if ta is not None: for name in self.tadata: if not numpy.isnan(self.tadata[name][idx]): candle.update({name: self.tadata[name][idx]}) return candle def getAnalyzer(): return self.analyzer def getMarket(self): return self.market def getName(self): return self.name def getIndicators(self): return self.indicators def loadCandlesticks(self, csdata=None): if csdata == None: self.csdata = self.trader.get_candlesticks(self.timeframe, size=self.candlesize, base_size=self.basesize) else: self.csdata = csdata self.analyzer = Analyzer(self.csdata)