From 45341bb24637c43a2e3c2dd01e8d496971777b91 Mon Sep 17 00:00:00 2001 From: Gerald Lonlas Date: Sun, 4 Mar 2018 20:21:49 -0800 Subject: [PATCH] Plot_profit.py: fix it and make it works with the new object model --- config.json.bak | 44 ------------- scripts/plot_profit.py | 142 ++++++++++++++++++++++++++++++----------- 2 files changed, 104 insertions(+), 82 deletions(-) delete mode 100644 config.json.bak diff --git a/config.json.bak b/config.json.bak deleted file mode 100644 index 053e83e3f..000000000 --- a/config.json.bak +++ /dev/null @@ -1,44 +0,0 @@ -{ - "max_open_trades": 3, - "stake_currency": "BTC", - "stake_amount": 0.005, - "fiat_display_currency": "USD", - "dry_run": true, - "unfilledtimeout": 600, - "bid_strategy": { - "ask_last_balance": 0.0 - }, - "exchange": { - "name": "bittrex", - "key": "", - "secret": "", - "pair_whitelist": [ - "BTC_ETH", - "BTC_LTC", - "BTC_ETC", - "BTC_DASH", - "BTC_ZEC", - "BTC_XLM", - "BTC_NXT", - "BTC_POWR", - "BTC_ADA", - "BTC_XMR" - ], - "pair_blacklist": [ - "BTC_DOGE" - ] - }, - "experimental": { - "use_sell_signal": false, - "sell_profit_only": false - }, - "telegram": { - "enabled": true, - "token": "387056091:AAEVz29u5KwphICqGB6c63RwZjqCd7Kh6T4", - "chat_id": "391939601" - }, - "initial_state": "running", - "internals": { - "process_throttle_secs": 5 - } -} diff --git a/scripts/plot_profit.py b/scripts/plot_profit.py index c51b29309..abdfed055 100755 --- a/scripts/plot_profit.py +++ b/scripts/plot_profit.py @@ -1,31 +1,43 @@ #!/usr/bin/env python3 +""" +Script to display profits + +Mandatory Cli parameters: +-p / --pair: pair to examine + +Optional Cli parameters +-c / --config: specify configuration file +-s / --strategy: strategy to use +--timerange: specify what timerange of data to use. +""" import sys import json +from typing import Dict import numpy as np +from datetime import datetime from plotly import tools from plotly.offline import plot import plotly.graph_objs as go +from freqtrade.arguments import Arguments +from freqtrade.configuration import Configuration +from freqtrade.analyze import Analyze +from freqtrade.logger import Logger + import freqtrade.optimize as optimize import freqtrade.misc as misc -from freqtrade.strategy.strategy import Strategy + +import pprint -def plot_parse_args(args): - parser = misc.common_args_parser('Graph profits') - # FIX: perhaps delete those backtesting options that are not feasible (shows up in -h) - misc.backtesting_options(parser) - misc.scripts_options(parser) - return parser.parse_args(args) +logger = Logger(name="Graph profits").get_logger() # data:: [ pair, profit-%, enter, exit, time, duration] -# data:: ['BTC_XMR', 0.00537847, '1511176800', '1511178000', 5057, 1] -# FIX: make use of the enter/exit dates to insert the -# profit more precisely into the pg array -def make_profit_array(data, px, filter_pairs=[]): +# data:: ["BTC_ETH", 0.0023975, "1515598200", "1515602100", "2018-01-10 07:30:00+00:00", 65] +def make_profit_array(data, px, min_date, interval, filter_pairs=[]): pg = np.zeros(px) # Go through the trades # and make an total profit @@ -35,10 +47,11 @@ def make_profit_array(data, px, filter_pairs=[]): if filter_pairs and pair not in filter_pairs: continue profit = trade[1] - tim = trade[4] - dur = trade[5] - ix = tim + dur - 1 + trade_sell_time = int(trade[3]) + + ix = define_index(min_date, trade_sell_time, interval) if ix < px: + logger.debug('[%s]: Add profit %s on %s', pair, profit, trade[4]) pg[ix] += profit # rewrite the pg array to go from @@ -64,47 +77,62 @@ def plot_profit(args) -> None: # We need to use the same pairs, same tick_interval # and same timeperiod as used in backtesting # to match the tickerdata against the profits-results + timerange = Arguments.parse_timerange(args.timerange) - filter_pairs = args.pair - - config = misc.load_config(args.config) - config.update({'strategy': args.strategy}) + config = Configuration(args).get_config() # Init strategy - strategy = Strategy() - strategy.init(config) + try: + analyze = Analyze({'strategy': config.get('strategy')}) + except AttributeError: + logger.critical( + 'Impossible to load the strategy. Please check the file "user_data/strategies/%s.py"', + config.get('strategy') + ) + exit() + # Take pairs from the cli otherwise switch to the pair in the config file + if args.pair: + filter_pairs = args.pair + filter_pairs = filter_pairs.split(',') + else: + filter_pairs = config['exchange']['pair_whitelist'] + + tick_interval = analyze.strategy.ticker_interval pairs = config['exchange']['pair_whitelist'] if filter_pairs: - filter_pairs = filter_pairs.split(',') pairs = list(set(pairs) & set(filter_pairs)) - print('Filter, keep pairs %s' % pairs) + logger.info('Filter, keep pairs %s' % pairs) - timerange = misc.parse_timerange(args.timerange) - tickers = optimize.load_data(args.datadir, pairs=pairs, - ticker_interval=strategy.ticker_interval, - refresh_pairs=False, - timerange=timerange) - dataframes = optimize.preprocess(tickers) + tickers = optimize.load_data( + datadir=args.datadir, + pairs=pairs, + ticker_interval=tick_interval, + refresh_pairs=False, + timerange=timerange + ) + dataframes = analyze.tickerdata_to_dataframe(tickers) # NOTE: the dataframes are of unequal length, # 'dates' is an merged date array of them all. dates = misc.common_datearray(dataframes) - max_x = dates.size + min_date = int(min(dates).timestamp()) + max_date = int(max(dates).timestamp()) + num_iterations = define_index(min_date, max_date, tick_interval) + 1 # Make an average close price of all the pairs that was involved. # this could be useful to gauge the overall market trend # We are essentially saying: # array <- sum dataframes[*]['close'] / num_items dataframes # FIX: there should be some onliner numpy/panda for this - avgclose = np.zeros(max_x) + avgclose = np.zeros(num_iterations) num = 0 for pair, pair_data in dataframes.items(): close = pair_data['close'] maxprice = max(close) # Normalize price to [0,1] - print('Pair %s has length %s' % (pair, len(close))) + logger.info('Pair %s has length %s' % (pair, len(close))) for x in range(0, len(close)): avgclose[x] += close[x] / maxprice # avgclose += close @@ -114,10 +142,16 @@ def plot_profit(args) -> None: # Load the profits results # And make an profits-growth array - filename = 'backtest-result.json' - with open(filename) as file: - data = json.load(file) - pg = make_profit_array(data, max_x, filter_pairs) + try: + filename = 'backtest-result.json' + with open(filename) as file: + data = json.load(file) + except FileNotFoundError: + logger.critical('File "backtest-result.json" not found. This script require backtesting ' + 'results to run.\nPlease run a backtesting with the parameter --export.') + exit(0) + + pg = make_profit_array(data, num_iterations, min_date, tick_interval, filter_pairs) # # Plot the pairs average close prices, and total profit growth @@ -128,6 +162,7 @@ def plot_profit(args) -> None: y=avgclose, name='Avg close price', ) + profit = go.Scattergl( x=dates, y=pg, @@ -140,7 +175,7 @@ def plot_profit(args) -> None: fig.append_trace(profit, 2, 1) for pair in pairs: - pg = make_profit_array(data, max_x, pair) + pg = make_profit_array(data, num_iterations, min_date, tick_interval, pair) pair_profit = go.Scattergl( x=dates, y=pg, @@ -151,6 +186,37 @@ def plot_profit(args) -> None: plot(fig, filename='freqtrade-profit-plot.html') +def define_index(min_date, max_date, interval): + """ + Return the index of a specific date + """ + return int((max_date - min_date) / (interval * 60)) + +def plot_parse_args(args): + """ + Parse args passed to the script + :param args: Cli arguments + :return: args: Array with all arguments + """ + arguments = Arguments(args, 'Graph profits') + arguments.scripts_options() + arguments.common_args_parser() + arguments.optimizer_shared_options(arguments.parser) + arguments.backtesting_options(arguments.parser) + + return arguments.parse_args() + + +def main(sysargv: Dict) -> None: + """ + This function will initiate the bot and start the trading loop. + :return: None + """ + logger.info('Starting Plot Dataframe') + plot_profit( + plot_parse_args(sysargv) + ) + + if __name__ == '__main__': - args = plot_parse_args(sys.argv[1:]) - plot_profit(args) + main(sys.argv[1:])