Refactoring the sell conditions evaluation to share the function with backtesting

This commit is contained in:
Jean-Baptiste LE STANG
2018-01-29 10:10:19 +01:00
parent e6c215104f
commit 94172091ae
2 changed files with 47 additions and 44 deletions

View File

@@ -12,7 +12,7 @@ import freqtrade.optimize as optimize
from freqtrade import exchange
from freqtrade.analyze import populate_buy_trend, populate_sell_trend
from freqtrade.exchange import Bittrex
from freqtrade.main import min_roi_reached
from freqtrade.main import should_sell
from freqtrade.persistence import Trade
from freqtrade.strategy.strategy import Strategy
@@ -50,8 +50,8 @@ def generate_text_table(
result.profit_percent.mean() * 100.0,
result.profit_BTC.sum(),
result.duration.mean() * ticker_interval,
result.profit.sum(),
result.loss.sum()
len(result[result.profit_BTC > 0]),
len(result[result.profit_BTC < 0])
])
# Append Total
@@ -61,18 +61,15 @@ def generate_text_table(
results.profit_percent.mean() * 100.0,
results.profit_BTC.sum(),
results.duration.mean() * ticker_interval,
results.profit.sum(),
results.loss.sum()
len(results[results.profit_BTC > 0]),
len(results[results.profit_BTC < 0])
])
return tabulate(tabular_data, headers=headers, floatfmt=floatfmt)
def get_trade_entry(pair, row, ticker, trade_count_lock, args):
def get_sell_trade_entry(pair, row, buy_subset, ticker, trade_count_lock, args):
stake_amount = args['stake_amount']
max_open_trades = args.get('max_open_trades', 0)
sell_profit_only = args.get('sell_profit_only', False)
stoploss = args.get('stoploss', -1)
use_sell_signal = args.get('use_sell_signal', False)
trade = Trade(open_rate=row.close,
open_date=row.date,
stake_amount=stake_amount,
@@ -81,26 +78,20 @@ def get_trade_entry(pair, row, ticker, trade_count_lock, args):
)
# calculate win/lose forwards from buy point
sell_subset = ticker[row.Index + 1:][['close', 'date', 'sell']]
sell_subset = ticker[ticker.date > row.date][['close', 'date', 'sell']]
for row2 in sell_subset.itertuples(index=True):
if max_open_trades > 0:
# Increase trade_count_lock for every iteration
trade_count_lock[row2.date] = trade_count_lock.get(row2.date, 0) + 1
current_profit_percent = trade.calc_profit_percent(rate=row2.close)
if (sell_profit_only and current_profit_percent < 0):
continue
if min_roi_reached(trade, row2.close, row2.date) or \
(row2.sell == 1 and use_sell_signal) or \
current_profit_percent <= stoploss:
current_profit_btc = trade.calc_profit(rate=row2.close)
buy_signal = buy_subset[buy_subset.date == row2.date].empty
if(should_sell(trade, row2.close, row2.date, buy_signal, row2.sell)):
return row2, (pair,
current_profit_percent,
current_profit_btc,
row2.Index - row.Index,
current_profit_btc > 0,
current_profit_btc < 0
)
trade.calc_profit_percent(rate=row2.close),
trade.calc_profit(rate=row2.close),
row2.Index - row.Index
), row2.date
return None
def backtest(args) -> DataFrame:
@@ -129,10 +120,11 @@ def backtest(args) -> DataFrame:
ticker = populate_sell_trend(populate_buy_trend(pair_data))
# for each buy point
lock_pair_until = None
buy_subset = ticker[ticker.buy == 1][['buy', 'open', 'close', 'date', 'sell']]
headers = ['buy', 'open', 'close', 'date', 'sell']
buy_subset = ticker[(ticker.buy == 1) & (ticker.sell == 0)][headers]
for row in buy_subset.itertuples(index=True):
if realistic:
if lock_pair_until is not None and row.Index <= lock_pair_until:
if lock_pair_until is not None and row.date <= lock_pair_until:
continue
if max_open_trades > 0:
# Check if max_open_trades has already been reached for the given date
@@ -143,11 +135,11 @@ def backtest(args) -> DataFrame:
# Increase lock
trade_count_lock[row.date] = trade_count_lock.get(row.date, 0) + 1
ret = get_trade_entry(pair, row, ticker,
trade_count_lock, args)
ret = get_sell_trade_entry(pair, row, buy_subset, ticker,
trade_count_lock, args)
if ret:
row2, trade_entry = ret
lock_pair_until = row2.Index
row2, trade_entry, next_date = ret
lock_pair_until = next_date
trades.append(trade_entry)
if record:
# Note, need to be json.dump friendly
@@ -162,7 +154,7 @@ def backtest(args) -> DataFrame:
if record and record.find('trades') >= 0:
logger.info('Dumping backtest results')
misc.file_dump_json('backtest-result.json', records)
labels = ['currency', 'profit_percent', 'profit_BTC', 'duration', 'profit', 'loss']
labels = ['currency', 'profit_percent', 'profit_BTC', 'duration']
return DataFrame.from_records(trades, columns=labels)