def _play(features): """Play an epoch with the given macd parameters""" time_base = features.index[0] now = time_base index = 0 # in case len(features) == 0 for index, feature in enumerate(features.values): macd = feature[1] if np.isnan(macd): continue now += du.secToNano(index * conf.TIME_INTERVAL * 60) im.timeTravel(now) if macd < -MIN_MACD: lm.buyOrSell(ActionEnum.SELL, CryptoEnum.XBT) elif macd > MIN_MACD: lm.buyOrSell(ActionEnum.BUY, CryptoEnum.XBT) if lm.gameOver(): # if log.VERBOSE >= 4: log.warning("game over:", index, "/", len(features)) return -42 score = lm.getGlobalBalanceInQuote() hodl = features["vwap"].iat[index] / features["vwap"].iat[0] * 100 # if log.VERBOSE >= 4: log.debug("score:", int(score - hodl), "(" + str(int(score)) + "-" + str(int(hodl)) + ")") return score # - hodl
def write(self, raw_data): """Write the given raw_data to the database, and cache it if needed""" if raw_data is None or raw_data.empty: return None if not fu.write(self.__class__.__name__, raw_data): log.warning("Couldn't write to database frame '" + self.__class__.__name__ + "'") return False self.cache(fresh_data=raw_data) return True
def __init__(self): self.model = None self.model_file = os.path.join(conf.DATA_DIR, self.__class__.__name__ + ".model") try: self.load() except OSError: log.warning("Couldn't load", self.__class__.__name__) self.dependencies = [] self._initDeps()
def _tooSoon(timestamp): """ Check if the previous transaction was too soon to start another one The delay is based on conf.TIME_INTERVAL. """ last_tx = getLastTx() if last_tx > 0 \ and timestamp - last_tx < du.secToNano(3 * conf.TIME_INTERVAL * 60): if LEDGERS[conf.QUOTE].verbose: log.warning("Previous transaction was too soon, waiting") return True return False
def _canBuy(): """ Check if you can buy crypto This is based on your balance and your current position. """ # if LAST_TX["type"] == "b": # return False if LEDGERS[conf.QUOTE].balance < MIN_BAL: if LEDGERS[conf.QUOTE].verbose: log.warning("Not enough", conf.QUOTE.name, "to buy") return False return True
def initGraph(log_lock, file_lock): """Launch an awesome matplotlib graph!""" log.setLock(log_lock) fu.setLock(file_lock) du.TIME_TRAVELER.setTime(None) sig.catchSignal() try: _getData() _initGraph() except Exception as e: log.warning("Something's bjorked in your graph :/") log.info("Try to run babao again with the env variable DEBUG_GRAPH set") # traceback.print_exc() raise e sys.exit(0) # we exit explicitly in the subprocess, to avoid double clean
def _canSell(crypto_enum): """ Check if you can sell crypto This is based on your balance and your current position. """ # if LAST_TX["type"] == "s": # return False if getBalanceInQuote(crypto_enum) < MIN_BAL: # this can be quite high actually # support.kraken.com/ \ # hc/en-us/articles/205893708-What-is-the-minimum-order-size- if LEDGERS[conf.QUOTE].verbose: log.warning("Not enough", crypto_enum.name, "to sell") return False return True
def fetch(self): if self.current_row is None: since = 0 # TODO: do we really need allllll the data? du.EPOCH else: since = self.current_row.name res = self._doRequest("Trades", { "pair": self.__class__.pair, "since": str(since) }) if res is None: self.up_to_date = False return None fresh_data = pd.DataFrame( res[self.__class__.pair], columns=[ # as returned by kraken api "price", "volume", "time", "buy-sell", "market-limit", "misc" ], dtype=float) if not fresh_data.empty: fresh_data["time"] = du.secToNano(fresh_data["time"]) if not fresh_data["time"].is_monotonic_increasing: log.warning("Sorting kraken data -.-") fresh_data.sort_values(by=['time'], inplace=True) fresh_data.loc[fresh_data["time"] == fresh_data["time"].iat[-1], "time"] = int(res["last"]) if since > fresh_data["time"].iat[0]: fresh_data.loc[fresh_data["time"] < since, "time"] = since fresh_data.index = fresh_data["time"] del fresh_data["misc"] del fresh_data["market-limit"] # this could be useful del fresh_data["buy-sell"] # idem del fresh_data["time"] self.up_to_date = len(fresh_data) != 1000 return fresh_data
def updateCurrentRow(self, current_row=None, timestamp=None): """Update the property self.current_row, useful for time travel""" global LAST_WRITE if timestamp is not None: # time travel if "Ledger" in self.__class__.__name__: return # we're going to the future current_row = self._readFromCache( since=timestamp, till=timestamp + du.secToNano(12 * 3600) # assuming there is at least one row per day? ) if not current_row.empty: current_row = current_row.iloc[0] if not current_row.empty: self.current_row = current_row if timestamp is not None: # time travel LAST_WRITE = current_row.name else: LAST_WRITE = max(LAST_WRITE, current_row.name) else: # spammy log.warning("Couldn't update current row for database '" + self.__class__.__name__ + "'")
def cache(self, fresh_data=None, since=None, till=None): """ Save some data to cache If ´fresh_data´ is given, append it to cache, otherwise read in database from ´since´ to ´till´ and cache it """ if fresh_data is not None: self._cache_data = self._cache_data.append(fresh_data) if not self._cache_data.empty: self._cache_data = self._cache_data.loc[ self._cache_data.index[-1] - du.secToNano(CACHE_REAL_TIME_LOOKBACK_DAYS * 24 * 3600):] else: log.debug("Caching data from", du.toStr(since), "to", du.toStr(till), "(" + self.__class__.__name__ + ")") self._cache_data = self._readFromFile(since, till) if not self._cache_data.empty: self.updateCurrentRow(self._cache_data.iloc[-1]) else: log.warning("Database '" + self.__class__.__name__ + "' is emtpy") self._cache_data = pd.DataFrame(columns=self.raw_columns)
def test_warning(): log.warning("warning")
def _getData(): """ Initialize ´DATA´ global Basically read ´conf.MAX_GRAPH_POINTS´ from data files """ global DATA if not os.path.isfile(conf.DB_FILE): log.warning("Data files not found... Is it your first time around?") return False if INDEX is None: crypto = conf.CRYPTOS[0] else: crypto = conf.CRYPTOS[INDEX.ind] inputs = [ lm.TRADES[crypto], lm.LEDGERS[conf.QUOTE], lm.LEDGERS[crypto] ] if conf.CURRENT_COMMAND == "backtest": for i in inputs: i._cache_data = None # pylint: disable=W0212 since = ib.SPLIT_DATE else: im.refreshInputs(inputs) since = lm.TRADES[crypto].current_row.name - du.secToNano( (MAX_LOOK_BACK + conf.MAX_GRAPH_POINTS) * conf.TIME_INTERVAL * 60 ) DATA = im.readInputs(inputs, since) DATA.rename( partial(re.sub, r'.*Trades.*-', ""), axis="columns", inplace=True ) DATA.rename( partial(re.sub, r'.*Ledger' + conf.QUOTE.name + '.*-', "quote-"), axis="columns", inplace=True ) DATA.rename( partial(re.sub, r'.*Ledger.*-', "crypto-"), axis="columns", inplace=True ) DATA = DATA.loc[ :, ['close', 'vwap', 'volume', 'quote-balance', 'crypto-balance'] ] DATA = indic.get(DATA, INDICATORS_COLUMNS) DATA["macd_line"], DATA["signal_line"], DATA["macd"] = indic.macd( DATA["vwap"], 46, 75, 22, True ) if conf.CURRENT_COMMAND == "backtest": DATA = DATA.fillna(0) else: DATA = DATA.dropna() DATA["total-balance"] = DATA["quote-balance"] \ + DATA["crypto-balance"] * DATA["close"] du.toDatetime(DATA) return True