From 029072c9af5bfd13ad1d8dc1e0b6026ded0ed0d9 Mon Sep 17 00:00:00 2001 From: gcarq Date: Mon, 5 Jun 2017 21:17:10 +0200 Subject: [PATCH] also use MACD indicator; minor changes --- analyze.py | 50 +++++++++++++++++++++++++------------------------ exchange.py | 11 +++++++++++ main.py | 14 ++++++++------ rpc/telegram.py | 9 +++++---- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/analyze.py b/analyze.py index 3bf7b8896..2e5945b54 100644 --- a/analyze.py +++ b/analyze.py @@ -1,10 +1,7 @@ +import time from datetime import timedelta import arrow -import matplotlib import logging - -matplotlib.use("Qt5Agg") -import matplotlib.pyplot as plt import requests from pandas.io.json import json_normalize from stockstats import StockDataFrame @@ -68,7 +65,8 @@ def populate_trends(dataframe): ] = 1 """ dataframe.loc[ - dataframe['stochrsi'] < 0.20, + (dataframe['stochrsi'] < 0.20) + & (dataframe['macd'] > dataframe['macds']), 'underpriced' ] = 1 dataframe.loc[dataframe['underpriced'] == 1, 'buy'] = dataframe['close'] @@ -103,27 +101,32 @@ def plot_dataframe(dataframe, pair): :return: None """ + import matplotlib + + matplotlib.use("Qt5Agg") + import matplotlib.pyplot as plt + # Three subplots sharing x axe - f, (ax1, ax2) = plt.subplots(2, sharex=True) + f, (ax1, ax2, ax3) = plt.subplots(3, sharex=True) f.suptitle(pair, fontsize=14, fontweight='bold') ax1.plot(dataframe.index.values, dataframe['close'], label='close') - ax1.plot(dataframe.index.values, dataframe['close_60_ema'], label='EMA(60)') - ax1.plot(dataframe.index.values, dataframe['close_120_ema'], label='EMA(120)') + ax1.plot(dataframe.index.values, dataframe['close_30_ema'], label='EMA(60)') + ax1.plot(dataframe.index.values, dataframe['close_90_ema'], label='EMA(120)') # ax1.plot(dataframe.index.values, dataframe['sell'], 'ro', label='sell') ax1.plot(dataframe.index.values, dataframe['buy'], 'bo', label='buy') ax1.legend() - #ax2.plot(dataframe.index.values, dataframe['macd'], label='MACD') - #ax2.plot(dataframe.index.values, dataframe['macds'], label='MACDS') - #ax2.plot(dataframe.index.values, dataframe['macdh'], label='MACD Histogram') - #ax2.plot(dataframe.index.values, [0] * len(dataframe.index.values)) - #ax2.legend() - - ax2.plot(dataframe.index.values, dataframe['stochrsi'], label='StochRSI') - ax2.plot(dataframe.index.values, [0.80] * len(dataframe.index.values)) - ax2.plot(dataframe.index.values, [0.20] * len(dataframe.index.values)) + ax2.plot(dataframe.index.values, dataframe['macd'], label='MACD') + ax2.plot(dataframe.index.values, dataframe['macds'], label='MACDS') + ax2.plot(dataframe.index.values, dataframe['macdh'], label='MACD Histogram') + ax2.plot(dataframe.index.values, [0] * len(dataframe.index.values)) ax2.legend() + ax3.plot(dataframe.index.values, dataframe['stochrsi'], label='StochRSI') + ax3.plot(dataframe.index.values, [0.80] * len(dataframe.index.values)) + ax3.plot(dataframe.index.values, [0.20] * len(dataframe.index.values)) + ax3.legend() + # Fine-tune figure; make subplots close to each other and hide x ticks for # all but bottom plot. f.subplots_adjust(hspace=0) @@ -134,10 +137,9 @@ def plot_dataframe(dataframe, pair): if __name__ == '__main__': while True: pair = 'BTC_ANT' - for pair in ['BTC_ANT', 'BTC_ETH', 'BTC_GNT', 'BTC_ETC']: - get_buy_signal(pair) - #dataframe = get_ticker_dataframe(pair) - #dataframe = populate_trends(dataframe) - #plot_dataframe(dataframe, pair) - #time.sleep(60) - + #for pair in ['BTC_ANT', 'BTC_ETH', 'BTC_GNT', 'BTC_ETC']: + # get_buy_signal(pair) + dataframe = get_ticker_dataframe(pair) + dataframe = populate_trends(dataframe) + plot_dataframe(dataframe, pair) + time.sleep(60) diff --git a/exchange.py b/exchange.py index 5ac1cca3d..5b4761625 100644 --- a/exchange.py +++ b/exchange.py @@ -169,3 +169,14 @@ class ApiWrapper(object): 'amount': entry['Quantity'], 'remaining': entry['QuantityRemaining'], } for entry in data['result']] + + def get_pair_detail_url(self, pair): + """ + Returns the market detail url for the given pair + :param pair: pair as str, format: BTC_ANT + :return: url as str + """ + if self.exchange == Exchange.POLONIEX: + raise NotImplemented('Not implemented') + elif self.exchange == Exchange.BITTREX: + return 'https://bittrex.com/Market/Index?MarketName={}'.format(pair.replace('_', '-')) diff --git a/main.py b/main.py index 983ecfc9a..46547b305 100755 --- a/main.py +++ b/main.py @@ -1,7 +1,6 @@ #!/usr/bin/env python import json import logging -import random import threading import time import traceback @@ -167,9 +166,10 @@ def handle_trade(trade): trade.close_date = datetime.utcnow() trade.open_order_id = order_id - message = '*{}:* Selling {} at rate `{:f} (profit: {}%)`'.format( + message = '*{}:* Selling [{}]({}) at rate `{:f} (profit: {}%)`'.format( trade.exchange.name, trade.pair.replace('_', '/'), + api_wrapper.get_pair_detail_url(trade.pair), trade.close_rate, round(current_profit, 2) ) @@ -206,9 +206,6 @@ def create_trade(stake_amount: float, exchange): if not whitelist: raise ValueError('No pair in whitelist') - ## Pick random pair and execute trade - #idx = random.randint(0, len(whitelist) - 1) - #pair = whitelist[idx] # Pick pair based on StochRSI buy signals for p in whitelist: if get_buy_signal(p): @@ -223,7 +220,12 @@ def create_trade(stake_amount: float, exchange): order_id = api_wrapper.buy(pair, open_rate, amount) # Create trade entity and return - message = '*{}:* Buying {} at rate `{:f}`'.format(exchange.name, pair.replace('_', '/'), open_rate) + message = '*{}:* Buying [{}]({}) at rate `{:f}`'.format( + exchange.name, + pair.replace('_', '/'), + api_wrapper.get_pair_detail_url(pair), + open_rate + ) logger.info(message) TelegramHandler.send_msg(message) return Trade(pair=pair, diff --git a/rpc/telegram.py b/rpc/telegram.py index 2a6f5d1e1..49ab022ec 100644 --- a/rpc/telegram.py +++ b/rpc/telegram.py @@ -70,7 +70,7 @@ class TelegramHandler(object): order = orders[0] if orders else None message = """ *Trade ID:* `{trade_id}` -*Current Pair:* [{pair}](https://bittrex.com/Market/Index?MarketName={pair}) +*Current Pair:* [{pair}]({market_url}) *Open Since:* `{date}` *Amount:* `{amount}` *Open Rate:* `{open_rate}` @@ -81,7 +81,8 @@ class TelegramHandler(object): *Open Order:* `{open_order}` """.format( trade_id=trade.id, - pair=trade.pair.replace('_', '-'), + pair=trade.pair, + market_url=api_wrapper.get_pair_detail_url(trade.pair), date=arrow.get(trade.open_date).humanize(), open_rate=trade.open_rate, close_rate=trade.close_rate, @@ -114,11 +115,11 @@ class TelegramHandler(object): durations_hours = [(t.close_date - t.open_date).total_seconds() / 3600.0 for t in trades] avg_duration = sum(durations_hours) / float(len(durations_hours)) markdown_msg = """ -*ROI:* `{profit_btc} BTC ({profit}%)` +*ROI:* `{profit_btc} ({profit}%)` *Trade Count:* `{trade_count}` *First Trade completed:* `{first_trade_date}` *Latest Trade completed:* `{latest_trade_date}` -*Avg. Stake Amount:* `{avg_stake_amount} BTC` +*Avg. Stake Amount:* `{avg_stake_amount}` *Avg. Duration:* `{avg_duration}` """.format( profit_btc=round(profit_amount, 8),