Parameter Scan Stack AUMΒΆ

overlays the AUM signals for each backtest in a paramter scan, see Parameter Scan Example

Python source code: ../../../src/boatwright/Visualization/param_scan_stack_aum.py

from ..Optimizations.ParameterScan import ParameterScan
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.colors as colors
import matplotlib.cm as cm
import mplcursors
import json


def param_scan_stack_aum(PS:ParameterScan, figsize=(8,5)):
    """
    overlays aum vs time for each backtest in the parameter scan. 
    """
    fig, ax = plt.subplots(figsize=figsize)
    fig.suptitle("Parameter Scan")
    ax.set_title(f"strategy: {PS.strategy_class.__name__}")
    ax.set_ylabel(PS.broker.quote_symbol)
    
    final_aums = [bt.data["aum"].iloc[-1] for bt in PS.backtests]
    norm = colors.Normalize(vmin=min(final_aums), vmax=max(final_aums))
    cmap = plt.get_cmap('winter')

    line_params = {}
    i = 0
    for bt in PS.backtests:
        i += 1
        dates = [dt.datetime.fromtimestamp(ts) for ts in bt.data["timestamp"]]
        color = cmap(norm(bt.data["aum"].iloc[-1]))
        line, = ax.plot(dates, bt.data["aum"], color=color)
        line_params[i] = json.dumps(bt.strategy.p)
        line.set_gid(i)
        
        # display parameters when mouse hovers over a line:
        def display_line_info(sel):
            line_label = line_params[sel.artist.get_gid()]
            annotation = sel.annotation
            annotation.set_text(line_label)

        mplcursors.cursor(line, hover=mplcursors.HoverMode.Transient).connect("add", display_line_info)
    
    dates = [dt.datetime.fromtimestamp(ts) for ts in bt.data["timestamp"]]
    buy_and_hold = (PS.broker.starting_aum / bt.data["close"].iloc[0]) * bt.data["close"]
    ax.plot(dates, buy_and_hold, label="buy & hold", color="black")

    fig.colorbar(cm.ScalarMappable(norm=norm, cmap=cmap), ax=ax, label="final aum")

    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d, %H:%M'))
    for label in ax.get_xticklabels(which='major'):
        label.set(rotation=30, horizontalalignment='right')
    
    ax.legend(loc="best")
    fig.tight_layout()
    return fig, ax