kieran-mackle / AutoTrader

A Python-based development platform for automated trading systems - from backtesting to optimisation to livetrading.
https://kieran-mackle.github.io/AutoTrader/
GNU General Public License v3.0
948 stars 217 forks source link

Export backtest results #9

Closed lleewwiiss closed 2 years ago

lleewwiiss commented 2 years ago

Is your feature request related to a problem? Please describe. While it is handy to have the plot to manually review the backtest results it would also be very useful to analyse the trading results automatically using a script to extract insights.

Describe the solution you'd like Export backtest results in a dataframe similar to what is displayed in the plot, with the additional functionality of being about to add additional features, possibly stored in the exit dictionary. This would be very beneficial for optimisation of strategies. Something similar to this possibly: Datetime Entry Price Exit Price Result Type Order type Stop loss Take profit Custom feature
12:12 12:12:00 $13.2 $14 Win Long market $13 $14 0.123
12:15 12:12:00 $14 $15 Loss Short market $15 $13 1.2

Describe alternatives you've considered I am not sure if this is already possible I had a look but couldn't see anything around export results, I apologise if I missed it in the documentation.

Additional context n/a

kieran-mackle commented 2 years ago

Something very similar to this is indeed already implemented, though not thoroughly documented.

When you run a backtest, all of the results are stored to the instance of AutoTrader created. Consider the example runfile from the demo repository:

from autotrader.autotrader import AutoTrader

at = AutoTrader()
at.configure(show_plot=True, verbosity=1)
at.add_strategy('macd')
at.backtest(start = '1/1/2020',
            end = '1/1/2021',
            initial_balance=1000,
            leverage = 30)
at.run()

After running this script, the results will be saved to the at object. You can view the overall results of the backtest in the at.backtest_results attribute, which will give you something like this:

{'no_trades': 145,
 'all_trades': {'profit_abs': 350.5171780349581,
  'profit_pc': 35.051717803495805,
  'MDD': -14.9,
  'avg_win': 25.196313068858135,
  'max_win': 32.078947994439936,
  'avg_loss': 16.613158031768084,
  'max_loss': 27.17222356058571,
  'win_rate': 45.51724137931034,
  'win_streak': 5,
  'lose_streak': 10,
  'longest_trade': '8 days, 11:00:00',
  'shortest_trade': '0:00:00',
  'avg_trade_duration': '22:20:41'},
 'no_open': 0,
 'no_cancelled': 11,
 'long_trades': {'no_trades': 82,
  'avg_long_win': 26.13811587497533,
  'max_long_win': 32.078947994439936,
  'avg_long_loss': 17.004832308050336,
  'max_long_loss': 27.17222356058571,
  'long_wr': 51.21951219512195},
 'short_trades': {'no_trades': 63,
  'avg_short_win': 23.548158158153033,
  'max_short_win': 29.864796071484516,
  'avg_short_loss': 16.21144082532475,
  'max_short_loss': 22.935793208796134,
  'short_wr': 38.095238095238095}}

Of course, if you are running a multi-bot backtest, you will likely be interested in the results specific to each trading bot. In this case, take a look at the at.bots_deployed attribute. This is a list containing the trading bots deployed, which each contain more specific data. See the AutoBot documentation for more info.

To get you started, try something like this. First, extract the first trading bot with bot = at.bots_deployed[0]. You can then look at the backtest summary in the bot.backtest_summary attribute. This is another dictionary with the following keys:

bot = at.bots_deployed[0]
bot.backtest_summary.keys()
>>> dict_keys(['data', 'NAV', 'balance', 'margin', 'trade_summary', 'indicators', 'instrument', 'interval', 'open_trades', 
                           'cancelled_trades'])

Most likely, you will be interested in the trade_summary, open_trades and cancelled_trades keys. They are pretty self-explanatory. For example, the trade summary is a dataframe with all trades taken, including key information. The columns of this dataframe is shown below. Of course, you can then save or post-process all the trade data from there.

ts = bot.backtest_summary['trade_summary']
ts.columns
>>> Index(['Order_ID', 'Order_price', 'Order_time', 'Entry_time', 'Entry', 'Size',
       'Stop_loss', 'Take_profit', 'Profit', 'Balance', 'Exit_time',
       'Exit_price', 'Trade_duration', 'date'],
      dtype='object')

There is a brief mention of all of this in the backtest tutorials, here.

Hope this helps!