def trades(trade_ids): db = app.get_db() cols = [ 'freq', "type", "Δprice", "macd", "rsi", "zscore", "time", "algo", "details" ] data, indexes = [], [] for _id in trade_ids: record = db.trades.find_one({"_id": _id}) indexes.append(record['pair']) ss1 = record['snapshots'][0] ss_new = record['snapshots'][-1] df = app.bot.dfc.loc[record['pair'], strtofreq(record['freqstr'])].tail(100) if len(record['orders']) > 1: c1 = ss1['candle'] c2 = ss_new['candle'] data.append([ c2['freqstr'], 'SELL', pct_diff(c1['close'], c2['close']), ss_new['indicators']['macd']['value'], ss_new['indicators']['rsi'], ss_new['indicators']['zscore'], to_relative_str(now() - record['start_time']), record['algo'], record['details'][-1]['section'].title() ]) # Buy trade else: c1 = ss1['candle'] data.append([ c1['freqstr'], 'BUY', 0.0, ss_new['indicators']['macd']['value'], ss_new['indicators']['rsi'], ss_new['indicators']['zscore'], "-", record['algo'], record['details'][-1]['section'].title() ]) if len(data) == 0: return tradelog("0 trades executed") df = pd.DataFrame(data, index=pd.Index(indexes), columns=cols) df = df[cols] lines = df.to_string( formatters={ cols[0]: ' {}'.format, cols[1]: ' {}'.format, cols[2]: ' {:+.2f}%'.format, cols[3]: ' {:+.3f}'.format, cols[4]: '{:.0f}'.format, cols[5]: '{}'.format, cols[5]: '{}'.format, cols[6]: '{}'.format }).split("\n") tradelog('-' * TRADELOG_WIDTH) tradelog("{} trade(s) executed:".format(len(df))) [tradelog(line) for line in lines]
def show_watchlist(stdscr): diff = tickers.diff db = get_db() ex = forex.getrate('CAD', utc_dtdate()) rows, colors = [], [] hdr = [ "Rank", "Sym", "Price", "Market Cap", "24h Vol", "1 Hour", "24 Hour", "7 Days", "30 Days", "1 Year" ] updated = [] for watch in db.watchlist.find(): cursor = db.cmc_tick.find({ "symbol": watch["symbol"] }).sort("date", -1).limit(1) if cursor.count() < 1: continue tckr = cursor.next() rows.append([ tckr["rank"], tckr["symbol"], tckr["price_usd"], tckr["mktcap_usd"], tckr["vol_24h_usd"], tckr["pct_1h"], tckr["pct_24h"], tckr["pct_7d"], diff(tckr["symbol"], tckr["price_usd"], "30D", to_format="percentage"), diff(tckr["symbol"], tckr["price_usd"], "1Y", to_format="percentage") ]) updated.append(tckr["date"].timestamp()) rows = sorted(rows, key=lambda x: int(x[0])) for row in rows: colors.append( [c.WHITE]*5 +\ [pnlcolor(row[5]), pnlcolor(row[6]), pnlcolor(row[7]), pnlcolor(row[8]), pnlcolor(row[9])] ) row[2] = pretty(ex * row[2], t='money') row[3] = pretty(ex * to_int(row[3]), t='money', abbr=True) row[4] = pretty(ex * to_int(row[4]), t='money', abbr=True) row[5] = pretty(row[5], t='pct', f='sign') row[6] = pretty(row[6], t='pct', f='sign') row[7] = pretty(row[7], t='pct', f='sign') row[8] = pretty(row[8], t='pct', f='sign') row[9] = pretty(row[9], t='pct', f='sign') # Print stdscr.clear() updated = to_relative_str(utc_datetime() - to_dt(max(updated))) + " ago" stdscr.addstr(0, 2, "Updated %s" % updated) stdscr.addstr(0, stdscr.getmaxyx()[1] - 5, CURRENCY.upper()) stdscr.addstr(1, 0, "") print_table(stdscr, ["Watchlist"], hdr, rows, colors, div=True)
def new_trades(trade_ids): db = app.get_db() dfc = app.bot.dfc cols = ["Type", "ΔPrice", "Slope", "Z-Score", "ΔZ-Score", "Time"] data, indexes = [], [] for _id in trade_ids: record = db.trades.find_one({"_id": _id}) freq_str = record['orders'][0]['candle']['freq'] indexes.append(record['pair']) candle = candles.newest(record['pair'], freq_str, df=dfc) ss1 = record['snapshots'][0] ss2 = record['snapshots'][-1] if len(record['orders']) > 1: c1 = record['orders'][0]['candle'] data.append([ 'SELL', pct_diff(c1['close'], candle['close']), ss2['price']['emaDiff'], ss2['price']['z-score'], ss2['price']['z-score'] - ss1['price']['z-score'], to_relative_str(now() - record['start_time']) ]) # Buy trade else: data.append([ 'BUY', 0.0, ss2['price']['emaDiff'], ss1['price']['z-score'], 0.0, "-" ]) if len(data) == 0: return tradelog("0 trades executed") df = pd.DataFrame(data, index=pd.Index(indexes), columns=cols) df = df[cols] lines = df.to_string( formatters={ cols[0]: ' {}'.format, cols[1]: ' {:+.2f}%'.format, cols[2]: ' {:+.2f}'.format, cols[3]: ' {:+.2f}'.format, cols[4]: ' {:+.2f}'.format, cols[5]: '{}'.format }).split("\n") tradelog("{} trade(s) executed:".format(len(df))) [tradelog(line) for line in lines]
def positions(): """Position summary. """ db = app.get_db() cols = ["freq", "price", "Δprice", "macd", "rsi", "zscore", "time", "algo"] data, indexes = [], [] opentrades = db.trades.find({'status': 'open'}) for record in opentrades: ss1 = record['snapshots'][0] c1 = ss1['candle'] ss_new = record['snapshots'][-1] freq = strtofreq(record['freqstr']) df = app.bot.dfc.loc[record['pair'], freq] dfmacd, phases = macd.histo_phases(df, record['pair'], record['freqstr'], 100) data.append([ c1['freqstr'], df.iloc[-1]['close'], pct_diff(c1['close'], df.iloc[-1]['close']), phases[-1].iloc[-1], signals.rsi(df['close'], 14), signals.zscore(df['close'], df.iloc[-1]['close'], 21), to_relative_str(now() - record['start_time']), record['algo'] ]) indexes.append(record['pair']) if opentrades.count() == 0: tradelog("0 open positions") else: df = pd.DataFrame(data, index=pd.Index(indexes), columns=cols) df = df[cols] lines = df.to_string( formatters={ cols[0]: ' {}'.format, cols[1]: ' {:g}'.format, cols[2]: ' {:+.2f}%'.format, cols[3]: ' {:+.3f}'.format, cols[4]: '{:.0f}'.format, cols[5]: '{}'.format, cols[6]: ' {}'.format }).split("\n") tradelog('-' * TRADELOG_WIDTH) tradelog("{} position(s):".format(len(df))) [tradelog(line) for line in lines] return df
def show_portfolio(stdscr): diff = tickers.diff t1 = Timer() db = get_db() total = 0.0 profit = 0 datarows, updated = [], [] ex = forex.getrate('CAD', utc_dtdate()) hdr = [ 'Rank', 'Sym', 'Price', 'Mcap', 'Vol 24h', '1 Hour', '24 Hour', '7 Day', '30 Days', '3 Months', 'Amount', 'Value', '/100' ] # Build datarows for hold in db.portfolio.find(): cursor = db.cmc_tick.find({ "symbol": hold["symbol"] }).sort("date", -1).limit(1) if cursor.count() < 1: continue tckr = cursor.next() value = round(hold['amount'] * ex * tckr['price_usd'], 2) profit += (tckr['pct_24h'] / 100) * value if tckr['pct_24h'] else 0.0 total += value updated.append(tckr["date"].timestamp()) datarows.append([ tckr['rank'], tckr['symbol'], ex * round(tckr['price_usd'], 2), ex * tckr.get('mktcap_usd', 0), ex * tckr["vol_24h_usd"], tckr["pct_1h"], tckr["pct_24h"], tckr["pct_7d"], diff(tckr["symbol"], tckr["price_usd"], "30D", to_format="percentage"), diff(tckr["symbol"], tckr["price_usd"], "90D", to_format="percentage"), hold['amount'], value, None ]) # Calculate porfolio % for datarow in datarows: datarow[12] = round((float(datarow[11]) / total) * 100, 2) # Sort by value datarows = sorted(datarows, key=lambda x: int(x[11]))[::-1] rows, colors = [], [] for datarow in datarows: colors.append([c.WHITE] * 5 + [pnlcolor(datarow[n]) for n in range(5, 10)] + [c.WHITE] * 3) rows.append([ datarow[0], datarow[1], pretty(datarow[2], t='money'), pretty(datarow[3], t='money', abbr=True), pretty(datarow[4], t='money', abbr=True), pretty(datarow[5], t='pct', f='sign'), pretty(datarow[6], t='pct', f='sign'), pretty(datarow[7], t='pct', f='sign'), pretty(datarow[8], t='pct', f='sign'), pretty(datarow[9], t='pct', f='sign'), pretty(datarow[10], abbr=True), pretty(datarow[11], t='money'), pretty(datarow[12], t='pct') ]) # Print title Row stdscr.clear() updated = to_relative_str(utc_datetime() - to_dt(max(updated))) + " ago" stdscr.addstr(0, 2, "Updated %s" % updated) stdscr.addstr(0, stdscr.getmaxyx()[1] - 5, CURRENCY.upper()) stdscr.addstr(1, 0, "") # Portfolio datatable print_table(stdscr, ["Portfolio"], hdr, rows, colors, align='right', colsp=2, div=True) stdscr.addstr(stdscr.getyx()[0] + 1, 0, "") # Summary table print_table(stdscr, ["Summary"], ["Holdings", "24 Hour", "Total Value"], [[ len(datarows), pretty(int(profit), t="money", f='sign', d=0), pretty(total, t='money') ]], [[c.WHITE, pnlcolor(profit), c.WHITE]], div=True)
def show_markets(stdscr): """Global market data. """ _diff = tickers.mkt_diff _to = pretty db = get_db() stdscr.clear() # Latest market (table) ex = forex.getrate('CAD', utc_dtdate()) hdr = [ 'Market Cap', '24h Volume', 'BTC Dominance', 'Markets', 'Currencies', '1 Hour', '24 Hour', '7 Day', '30 Day' ] mktdata = list(db.cmc_mkt.find().limit(1).sort('date', -1)) if len(mktdata) == 0: return log.error("db.cmc_mkt empty") rows, colors = [], [] for mkt in mktdata: rows.append([ _to(ex * mkt['mktcap_usd'], t="money", abbr=True), _to(ex * mkt['vol_24h_usd'], t="money", abbr=True), _to(mkt['pct_mktcap_btc'], t="pct"), _to(mkt['n_markets'], d=0), _to(mkt['n_assets'] + mkt['n_currencies'], d=0), _to(_diff('1H', to_format='percentage'), t="pct", f="sign"), _to(_diff('24H', to_format='percentage'), t="pct", f="sign"), _to(_diff('7D', to_format='percentage'), t="pct", f="sign"), "-" ]) colors.append([c.WHITE] * 5 + [pnlcolor(rows[-1][col]) for col in range(5, 9)]) stdscr.addstr(0, 2, "< Home") page_title = "Markets (%s)" % CURRENCY.upper() stdscr.addstr(0, int(stdscr.getmaxyx()[1] / 2 - len(page_title) / 2), page_title) updated = "Updated " + to_relative_str(utc_datetime() - mktdata[0]["date"]) + " ago" stdscr.addstr(0, stdscr.getmaxyx()[1] - len(updated) - 2, updated) stdscr.addstr(2, 0, "") print_table(stdscr, ["Current"], hdr, rows, colors, div=True) # Weekly market (table) start = utc_dtdate() + timedelta(days=-14) cursor = db.cmc_mkt.find({ "date": { "$gte": start, "$lt": utc_dtdate() } }).sort('date', -1) if cursor.count() < 1: return log.error("no data for weekly markets") hdr = [ "Date", "Mcap Open", "Mcap High", "Mcap Low", "Mcap Close", "Mcap Spread", "Mcap SD", "Volume", "BTC Dom" ] rows, colors = [], [] for mkt in cursor: ex = forex.getrate('CAD', mkt["date"]) rows.append([ mkt["date"].strftime("%b-%d"), _to(ex * mkt["mktcap_open_usd"], t='money', d=1, abbr=True), _to(ex * mkt["mktcap_high_usd"], t='money', d=1, abbr=True), _to(ex * mkt["mktcap_low_usd"], t='money', d=1, abbr=True), _to(ex * mkt["mktcap_close_usd"], t='money', d=1, abbr=True), _to(mkt["mktcap_spread_usd"] / mkt["mktcap_low_usd"] * 100, t='pct'), _to(ex * mkt["mktcap_std_24h_usd"], t='money', d=1, abbr=True), _to(ex * mkt['vol_24h_close_usd'], t="money", d=1, abbr=True), _to(ex * mkt['btc_mcap'], t="pct") ]) colors.append([c.WHITE] * 9) cursor.rewind() df = pd.DataFrame(list(cursor)) colors[df["mktcap_high_usd"].idxmax()][2] = c.GREEN colors[df["mktcap_low_usd"].idxmin()][3] = c.RED colors[df["vol_24h_close_usd"].idxmax()][7] = c.GREEN stdscr.addstr(stdscr.getyx()[0] + 1, 0, "") print_table(stdscr, ["Recent"], hdr, rows, colors, div=True)
def update(_freq_str): """Evaluate Binance market data and execute buy/sell trades. """ global n_cycles, freq_str, freq trade_ids = [] freq_str = _freq_str freq = strtofreq[freq_str] t1 = Timer() db = get_db() # Update candles updated by websocket app.bot.dfc = candles.merge_new(app.bot.dfc, pairs, span=None) tradelog('*' * 80) duration = to_relative_str(now() - start) hdr = "Cycle #{}, Period {} {:>%s}" % (61 - len(str(n_cycles))) tradelog(hdr.format(n_cycles, freq_str, duration)) tradelog('*' * 80) # Output candle signals to siglog if freq_str in siglog_freq: siglog('-' * 80) for pair in pairs: printer.candle_sig(candles.newest(pair, freq_str, df=app.bot.dfc)) # Evaluate existing positions active = list(db.trades.find({'status': 'open', 'freq': freq_str})) for trade in active: candle = candles.newest(trade['pair'], freq_str, df=app.bot.dfc) result = strategy.update(candle, trade) print('{} {} {}'.format(candle['pair'], candle['freq'], result['snapshot']['details'])) if result['action'] == 'SELL': trade_ids += [sell(trade, candle, criteria=result)] else: db.trades.update_one({"_id": trade["_id"]}, {"$push": { "snapshots": result['snapshot'] }}) # Inverse active list and evaluate opening new positions inactive = sorted(list(set(pairs) - set([n['pair'] for n in active]))) for pair in inactive: candle = candles.newest(pair, freq_str, df=app.bot.dfc) results = strategy.evaluate(candle) for res in results: print('{} {} {}'.format(candle['pair'], candle['freq'], res['snapshot']['details'])) if res['action'] == 'BUY': trade_ids += [buy(candle, criteria=res)] tradelog('-' * 80) printer.new_trades([n for n in trade_ids if n]) tradelog('-' * 80) printer.positions('open') tradelog('-' * 80) printer.positions('closed') n_cycles += 1
def positions(_type): """Position summary. @_type: 'open', 'closed' @start: datetime.datetime for closed trades """ from docs.rules import TRADING_PAIRS as pairs db = app.get_db() dfc = app.bot.dfc if _type == 'open': cols = ["ΔPrice", "Slope", " Z-Score", " ΔZ-Score", "Macd", "Time"] data, indexes = [], [] _trades = list( db.trades.find({ 'status': 'open', 'pair': { "$in": pairs } })) for record in _trades: c1 = record['orders'][0]['candle'] c2 = candles.newest(record['pair'], c1['freq'], df=dfc) ss1 = record['snapshots'][0] ss2 = record['snapshots'][-1] data.append([ pct_diff(c1['close'], c2['close']), ss2['price']['emaDiff'], ss2['price']['z-score'], ss2['price']['z-score'] - ss1['price']['z-score'], ss2['macd']['value'], to_relative_str(now() - record['start_time']) ]) indexes.append(record['pair']) if len(_trades) == 0: tradelog("0 open positions") else: df = pd.DataFrame(data, index=pd.Index(indexes), columns=cols) df = df[cols] lines = df.to_string( formatters={ cols[0]: ' {:+.2f}%'.format, cols[1]: ' {:+.2f}%'.format, cols[2]: ' {:.2f}'.format, cols[3]: ' {:+.2f}'.format, cols[4]: ' {:+.2f}'.format, cols[5]: '{}'.format }).split("\n") tradelog("{} position(s):".format(len(df))) [tradelog(line) for line in lines] return df elif _type == 'closed': if datetime.now().time().hour >= 8: start = dateparser.parse("8 am today").replace( tzinfo=tzlocal.get_localzone()).astimezone(pytz.utc) else: start = dateparser.parse("8 am yesterday").replace( tzinfo=tzlocal.get_localzone()).astimezone(pytz.utc) closed = list( db.trades.find({ 'status': 'closed', 'end_time': { '$gte': start } })) #print("%s trades today ending after %s" % (len(closed), start)) n_win, pct_net_gain = 0, 0 for n in closed: if n['pct_net_gain'] > 0: n_win += 1 pct_net_gain += n['pct_net_gain'] ratio = (n_win / len(closed)) * 100 if len(closed) > 0 else 0 tradelog("{} of {} trade(s) today were profitable.".format( n_win, len(closed))) duration = to_relative_str(now() - start) tradelog("{:+.2f}% net profit today.".format(pct_net_gain))