code: def plot_bt_predictions2(
      bt_pred_df,
      metrics=smape,
      split_key_list=None,
      figsize=None,
      include_vline=True,
      title="",
      fontsize=20,
      markersize=50,
      lw=2,
      fig_dir=None,
      is_visible=True,
      fix_xylim=True,
      export_gif=False,
  ):
      """a different style backtest plot compare to `plot_bt_prediction` where it writes separate plot for each split;
      this is also used to produce an animation to summarize every split
      """
      if figsize is None:
          figsize = (16, 8)
  
      if fig_dir:
          if not os.path.isdir(fig_dir) or not os.path.exists(fig_dir):
              raise PlotException(
                  "Invalid or non-existing directory use specified: {}.".format(
                      os.path.abspath(fig_dir)
                  )
              )
          fig_paths = list()
  
      metric_vals = bt_pred_df.groupby(
          BacktestFitKeys.SPLIT_KEY.value
      ).apply(
          lambda x: metrics(
              x[~x[BacktestFitKeys.TRAIN_FLAG.value]][
                  BacktestFitKeys.ACTUAL.value
              ],
              x[~x[BacktestFitKeys.TRAIN_FLAG.value]][
                  BacktestFitKeys.PREDICTED.value
              ],
          )
      )
  
      if split_key_list is None:
          split_key_list_ = bt_pred_df[
              BacktestFitKeys.SPLIT_KEY.value
          ].unique()
      else:
          split_key_list_ = split_key_list
  
      if fix_xylim:
          all_values = np.concatenate(
              (
                  bt_pred_df[BacktestFitKeys.ACTUAL.value].values,
                  bt_pred_df[BacktestFitKeys.PREDICTED.value].values,
              )
          )
          ylim = (np.min(all_values) * 0.99, np.max(all_values) * 1.01)
          xlim = (
              bt_pred_df[BacktestFitKeys.DATE.value].values[0],
              bt_pred_df[BacktestFitKeys.DATE.value].values[-1],
          )
  
      for idx, split_key in enumerate(split_key_list_):
          fig, ax = plt.subplots(1, 1, figsize=figsize)
          tmp = bt_pred_df[
              bt_pred_df[BacktestFitKeys.SPLIT_KEY.value] == split_key
          ].copy()
          ax.plot(
              tmp[BacktestFitKeys.DATE.value],
              tmp[BacktestFitKeys.PREDICTED.value],
              color=PredPal.PREDICTION_LINE.value,
              lw=lw,
          )
  
          train_df = tmp.loc[tmp[BacktestFitKeys.TRAIN_FLAG.value], :]
          ax.scatter(
              train_df[BacktestFitKeys.DATE.value],
              train_df[BacktestFitKeys.ACTUAL.value],
              marker=".",
              color=PredPal.ACTUAL_OBS.value,
              alpha=0.8,
              s=markersize,
              label="train response",
          )
  
          test_df = tmp.loc[~tmp[BacktestFitKeys.TRAIN_FLAG.value], :]
          ax.scatter(
              test_df[BacktestFitKeys.DATE.value],
              test_df[BacktestFitKeys.ACTUAL.value],
              marker=".",
              color=PredPal.TEST_OBS.value,
              alpha=0.8,
              s=markersize,
              label="test response",
          )
  
          ax.set_title(
              label="split {}; {} {:.3f}".format(
                  split_key, metrics.__name__, metric_vals[split_key]
              )
          )
          if include_vline:
              cutoff_date = tmp[~tmp[BacktestFitKeys.TRAIN_FLAG.value]][
                  BacktestFitKeys.DATE.value
              ].min()
              ax.axvline(
                  x=cutoff_date,
                  linestyle="--",
                  color=PredPal.HOLDOUT_VERTICAL_LINE.value,
                  alpha=0.8,
              )
          if fix_xylim:
              ax.set_xlim(xlim)
              ax.set_ylim(ylim)
  
          ax.legend()
          plt.suptitle(title, fontsize=fontsize)
          fig.tight_layout()
  
          if fig_dir:
              fig_path = "{}/splits_{}.png".format(fig_dir, idx)
              fig_paths.append(fig_path)
              fig.savefig(fig_path)
          if is_visible:
              plt.show()
          else:
              plt.close()
  
      if fig_dir and export_gif:
          package_name = "imageio"
          try:
              pkg_resources.get_distribution(package_name)
              import imageio
  
              with imageio.get_writer(
                  "{}/orbit-backtest.gif".format(fig_dir), mode="I"
              ) as writer:
                  for fig_path in fig_paths:
                      image = imageio.imread(fig_path)
                      writer.append_data(image)
          except pkg_resources.DistributionNotFound:
              logger.error(
                  (
                      "{} not installed, which is necessary for gif animation".format(
                          package_name
                      )
                  )
              )
  
imports: import matplotlib.pyplot
  import seaborn
  import pandas
  import numpy
  import math
  import os
  import pkg_resources
  import statsmodels.api
  from scipy import stats
  from ..constants.constants import PredictionKeys
  from orbit.utils.general import is_empty_dataframe, is_ordered_datetime
  from ..constants.constants import BacktestFitKeys
  from ..constants.palette import PredictionPaletteClassic
  from orbit.constants import palette
  from orbit.diagnostics.metrics import smape
  from orbit.utils.plot import orbit_style_decorator
  from ..exceptions import PlotException
  import logging
label_desc: Use image node_id 4 for calling a global function with example usage: plot_bt_predictions2(bt_pred_df, metrics, split_key_list, figsize, include_vline, title, fontsize, markersize, lw, fig_dir, is_visible, fix_xylim, export_gif) without return types