code: def _pred_turnover(
      pred_label: pd.DataFrame, N=5, lag=1, **kwargs
  ) -> tuple:
      pred = pred_label.copy()
      pred["score_last"] = pred.groupby(level="instrument")[
          "score"
      ].shift(lag)
      top = pred.groupby(level="datetime").apply(
          lambda x: 1
          - x.nlargest(len(x) // N, columns="score")
          .index.isin(
              x.nlargest(len(x) // N, columns="score_last").index
          )
          .sum()
          / (len(x) // N)
      )
      bottom = pred.groupby(level="datetime").apply(
          lambda x: 1
          - x.nsmallest(len(x) // N, columns="score")
          .index.isin(
              x.nsmallest(len(x) // N, columns="score_last").index
          )
          .sum()
          / (len(x) // N)
      )
      r_df = pd.DataFrame(
          {
              "Top": top,
              "Bottom": bottom,
          }
      )
      turnover_figure = ScatterGraph(
          r_df,
          layout=dict(
              title="Top-Bottom Turnover",
              xaxis=dict(
                  tickangle=45,
                  rangebreaks=kwargs.get(
                      "rangebreaks",
                      guess_plotly_rangebreaks(r_df.index),
                  ),
              ),
          ),
      ).figure
      return (turnover_figure,)
  
file_path: qlib/qlib/contrib/report/analysis_model/analysis_model_performance.py
imports: from functools import partial
  import pandas
  import plotly.graph_objs
  import statsmodels.api
  import matplotlib.pyplot
  from scipy import stats
  from typing import Sequence
  from qlib.typehint import Literal
  from ..graph import ScatterGraph, SubplotsGraph, BarGraph, HeatmapGraph
  from ..utils import guess_plotly_rangebreaks
label_desc: Use image node_id 5 for calling a global function with example usage: _pred_turnover(pred_label, N, lag) and returns: turnover_figure