Skip to content

Commit

Permalink
docs: renamed relevant classes for clarity
Browse files Browse the repository at this point in the history
  • Loading branch information
kieran-mackle committed Aug 3, 2022
1 parent 5a8d146 commit 14f80ea
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 47 deletions.
9 changes: 5 additions & 4 deletions autotrader/autoplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ def plot(self,
topsource.add(account_hist[['NAV', 'equity']].min(1), 'Low')
topsource.add(account_hist[['NAV', 'equity']].max(1), 'High')

# TODO - update below, trade_history is more like iso_pos history
trade_summary = trade_results.trade_history
# Get isolated position summary
trade_summary = trade_results.isolated_position_history
indicators = trade_results.indicators
open_trades = trade_results.open_trades
open_trades = trade_results.open_isolated_positions
cancelled_trades = trade_results.cancelled_orders

top_fig = self._plot_lineV2(topsource, main_plot, "NAV", new_fig=True,
Expand Down Expand Up @@ -479,7 +479,7 @@ def _plot_multibot_backtest(self, backtest_results):
output_file("autotrader_backtest.html", title = "AutoTrader Multi-Bot Backtest Results")
linked_crosshair = CrosshairTool(dimensions='both')
reindexed_acc_hist = self._reindex_data(backtest_results.account_history)
trade_history = backtest_results.trade_history
trade_history = backtest_results.isolated_position_history
# holding_history = backtest_results.holding_history

# Account Balance
Expand Down Expand Up @@ -520,6 +520,7 @@ def _plot_multibot_backtest(self, backtest_results):
self.autoscale_args = {'y_range': navfig.y_range, 'source': acc_hist}

# Cumultive returns plot
# TODO - review calculation
returns_per_instrument = [trade_history.profit[trade_history.instrument == i].cumsum() for i in instruments]
cplfig = figure(plot_width = navfig.plot_width,
plot_height = self._top_fig_height,
Expand Down
6 changes: 3 additions & 3 deletions autotrader/autotrader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ def print_trade_results(self, trade_results: TradeAnalysis = None) -> None:
round(pc_return, 1)))
if no_trades > 0:
print("Total no. trades: {}".format(no_trades))
print("Total fees: ${}".format(round(total_fees, 3)))
print("Total fees paid: ${}".format(round(total_fees, 3)))
print("Trade win rate: {}%".format(round(win_rate, 1)))
print("Maximum drawdown: {}%".format(round(max_drawdown*100, 2)))
print("Max win: ${}".format(round(max_win, 2)))
Expand Down Expand Up @@ -1171,7 +1171,7 @@ def print_trade_results(self, trade_results: TradeAnalysis = None) -> None:
if len(trade_results.instruments_traded) > 1:
# Mutliple instruments traded
instruments = trade_results.instruments_traded
trade_history = trade_results.trade_history
trade_history = trade_results.isolated_position_history

total_no_trades = []
max_wins = []
Expand Down Expand Up @@ -1710,7 +1710,7 @@ def shutdown(self):
f"{round((backtest_end_time - self._backtest_start_time), 3)} s).")
self.print_trade_results()

if self._show_plot and len(self.trade_results.trade_history) > 0:
if self._show_plot and len(self.trade_results.isolated_position_history) > 0:
self.plot_backtest()

elif self._scan_mode and self._show_plot:
Expand Down
1 change: 1 addition & 0 deletions autotrader/brokers/virtual/broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,7 @@ def _fill_order(self,

# Create Trade and append to fills
# TODO - look into where order_price and order_time originate
# Looks like the order price is repeated for closing orders...
fill = Trade(
order=order,
fill_time=fill_time,
Expand Down
82 changes: 43 additions & 39 deletions autotrader/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,31 +305,35 @@ class TradeAnalysis:
holding_history : pd.DataFrame
A timeseries summary of holdings during the trading period, by portfolio
allocation fraction.
trade_history : pd.DataFrame
isolated_position_history : pd.DataFrame
A timeseries history of trades taken during the trading period.
order_history : pd.DataFrame
A timeseries history of orders placed during the trading period.
open_trades : pd.DataFrame
Trades which remained open at the end of the trading period.
open_isolated_positions : pd.DataFrame
Positions which remained open at the end of the trading period.
cancelled_orders : pd.DataFrame
Orders which were cancelled during the trading period.
trade_history : pd.DataFrame
A history of all trades (fills) made during the trading period.
"""
def __init__(self, broker, instrument: str = None,
process_holding_history: bool = True):
# TODO - review the attributes below for name clarity
# trades - refer to fills
# will need to maintain 'trade_history' for plotting
# TODO - need to review how calculations are performed, eg. no_trades,
# trade_duration

# Meta data
self.brokers_used = None
self.broker_results = None
self.instruments_traded = None

# Histories
self.account_history = None
# self.holding_history = None
self.trade_history = None
self.isolated_position_history = None
self.open_isolated_positions = None
self.order_history = None
self.open_trades = None
self.cancelled_orders = None
self.fills = None
self.trade_history = None

self.analyse_account(broker, instrument, process_holding_history)

Expand Down Expand Up @@ -373,7 +377,7 @@ def analyse_account(self, broker, instrument: str = None,
orders = TradeAnalysis.create_trade_summary(orders=all_orders,
instrument=instrument,
broker_name=broker_name)
fills = TradeAnalysis.create_fill_summary(fills=broker.fills,
trade_history = TradeAnalysis.create_fill_summary(fills=broker.fills,
broker_name=broker_name)

# Construct account history
Expand Down Expand Up @@ -410,11 +414,11 @@ def analyse_account(self, broker, instrument: str = None,
'instruments_traded': list(orders.instrument.unique()),
'account_history': account_history,
'holding_history': holding_history,
'trade_history': trades,
'isolated_position_history': trades,
'order_history': orders,
'open_trades': trades[trades.status == 'open'],
'open_isolated_positions': trades[trades.status == 'open'],
'cancelled_orders': orders[orders.status == 'cancelled'],
'fills': fills,
'trade_history': trade_history,
}

# Save all results
Expand All @@ -427,14 +431,13 @@ def analyse_account(self, broker, instrument: str = None,
def _aggregate_across_brokers(self, broker_results):
"""Aggregates trading history across all broker instances.
"""

brokers_used = []
instruments_traded = []
open_trades = pd.DataFrame()
open_isolated_positions = pd.DataFrame()
cancelled_orders = pd.DataFrame()
trade_history = pd.DataFrame()
isolated_position_history = pd.DataFrame()
order_history = pd.DataFrame()
fills = pd.DataFrame()
trade_history = pd.DataFrame()
account_history = None
for broker, results in broker_results.items():
orders = results['order_history']
Expand Down Expand Up @@ -462,23 +465,22 @@ def _aggregate_across_brokers(self, broker_results):
# Use new index
account_history = new_index + results['account_history']

# Concatenate trades, orders and fills
open_trades = pd.concat([open_trades, results['open_trades']])
# Concatenate trades, orders and trade_history
open_isolated_positions = pd.concat([open_isolated_positions, results['open_isolated_positions']])
cancelled_orders = pd.concat([cancelled_orders, results['cancelled_orders']])
trade_history = pd.concat([trade_history, results['trade_history']])
isolated_position_history = pd.concat([isolated_position_history, results['isolated_position_history']])
order_history = pd.concat([order_history, results['order_history']])
fills = pd.concat([fills, results['fills']])
trade_history = pd.concat([trade_history, results['trade_history']])

# Assign attributes
self.brokers_used = brokers_used
self.instruments_traded = instruments_traded
self.account_history = account_history
# self.holding_history = holding_history
self.trade_history = trade_history
self.isolated_position_history = isolated_position_history
self.order_history = order_history
self.open_trades = open_trades
self.open_isolated_positions = open_isolated_positions
self.cancelled_orders = cancelled_orders
self.fills = fills
self.trade_history = trade_history


@staticmethod
Expand Down Expand Up @@ -516,7 +518,6 @@ def create_trade_summary(trades: dict = None,
broker_name: str = None) -> pd.DataFrame:
"""Creates a summary dataframe for trades and orders.
"""

instrument = None if isinstance(instrument, list) else instrument

if trades is not None:
Expand Down Expand Up @@ -627,10 +628,11 @@ def create_trade_summary(trades: dict = None,
def summary(self):
"""Constructs a summary of trades taken."""
trade_results = {}
cpl = self.trade_history.profit.cumsum()
# TODO - review below calculation
cpl = self.isolated_position_history.profit.cumsum()

# All trades
no_trades = len(self.trade_history[self.trade_history['status'] == 'closed'])
no_trades = len(self.trade_history)
trade_results['no_trades'] = no_trades

if len(self.account_history) > 0:
Expand All @@ -650,20 +652,22 @@ def summary(self):
trade_results['pc_return'] = pc_return

if no_trades > 0:
# TODO - need to review calculation of all below
# Think in terms of positions, not 'trades'
trade_results['all_trades'] = {}
wins = self.trade_history[self.trade_history.profit > 0]
wins = self.isolated_position_history[self.isolated_position_history.profit > 0]
avg_win = np.mean(wins.profit)
max_win = np.max(wins.profit)
loss = self.trade_history[self.trade_history.profit < 0]
loss = self.isolated_position_history[self.isolated_position_history.profit < 0]
avg_loss = abs(np.mean(loss.profit))
max_loss = abs(np.min(loss.profit))
win_rate = 100*len(wins)/no_trades
longest_win_streak, longest_lose_streak = get_streaks(self.trade_history)
avg_trade_duration = np.nanmean(self.trade_history.trade_duration.values)
min_trade_duration = np.nanmin(self.trade_history.trade_duration.values)
max_trade_duration = np.nanmax(self.trade_history.trade_duration.values)
longest_win_streak, longest_lose_streak = get_streaks(self.isolated_position_history)
avg_trade_duration = np.nanmean(self.isolated_position_history.trade_duration.values)
min_trade_duration = np.nanmin(self.isolated_position_history.trade_duration.values)
max_trade_duration = np.nanmax(self.isolated_position_history.trade_duration.values)
max_drawdown = min(self.account_history.drawdown)
total_fees = self.trade_history.fees.sum()
total_fees = self.trade_history.fee.sum()

trade_results['all_trades']['avg_win'] = avg_win
trade_results['all_trades']['max_win'] = max_win
Expand All @@ -680,11 +684,11 @@ def summary(self):
trade_results['all_trades']['total_fees'] = total_fees

# Cancelled and open orders
trade_results['no_open'] = len(self.open_trades)
trade_results['no_open'] = len(self.open_isolated_positions)
trade_results['no_cancelled'] = len(self.cancelled_orders)

# Long trades
long_trades = self.trade_history[self.trade_history['direction'] > 0]
long_trades = self.isolated_position_history[self.isolated_position_history['direction'] > 0]
no_long = len(long_trades)
trade_results['long_trades'] = {}
trade_results['long_trades']['no_trades'] = no_long
Expand All @@ -704,7 +708,7 @@ def summary(self):
trade_results['long_trades']['long_wr'] = long_wr

# Short trades
short_trades = self.trade_history[self.trade_history['direction'] < 0]
short_trades = self.isolated_position_history[self.isolated_position_history['direction'] < 0]
no_short = len(short_trades)
trade_results['short_trades'] = {}
trade_results['short_trades']['no_trades'] = no_short
Expand Down
3 changes: 2 additions & 1 deletion tests/test_backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,5 @@ def test_multibot_macd_backtest():
assert bt_results['short_trades']['no_trades'] == 48, "Incorrect number "+\
"of short trades (multi-instrument backtest)"

test_macd_backtest()
test_macd_backtest()
# test_multibot_macd_backtest()

0 comments on commit 14f80ea

Please sign in to comment.