class_docstr: Motivation:
      PortfolioMetrics is for supporting portfolio related metrics.
  
  Implementation:
  
      daily portfolio metrics of the account
      contain those followings: return, cost, turnover, account, cash, bench, value
      For each step(bar/day/minute), each column represents
      - return: the return of the portfolio generated by strategy **without transaction fee**.
      - cost: the transaction fee and slippage.
      - account: the total value of assets(cash and securities are both included) in user account based on the close price of each step.
      - cash: the amount of cash in user's account.
      - bench: the return of the benchmark
      - value: the total value of securities/stocks/instruments (cash is excluded).
  
      update report
class_docstr_tok: ["Motivation",":","PortfolioMetrics","is","for","supporting","portfolio","related","metrics",".","Implementation",":","daily","portfolio","metrics","of","the","account","contain","those","followings",":","return",",","cost",",","turnover",",","account",",","cash",",","bench",",","value","For","each","step","(","bar\/day\/minute",")",",","each","column","represents","-","return",":","the","return","of","the","portfolio","generated","by","strategy","*","*","without","transaction","fee","*","*",".","-","cost",":","the","transaction","fee","and","slippage",".","-","account",":","the","total","value","of","assets","(","cash","and","securities","are","both","included",")","in","user","account","based","on","the","close","price","of","each","step",".","-","cash",":","the","amount","of","cash","in","user","'s","account",".","-","bench",":","the","return","of","the","benchmark","-","value",":","the","total","value","of","securities\/stocks\/instruments","(","cash","is","excluded",")",".","update","report"]
code: def _cal_benchmark(
      benchmark_config: Optional[dict], freq: str
  ) -> Optional[pd.Series]:
      if benchmark_config is None:
          return None
      benchmark = benchmark_config.get("benchmark", CSI300_BENCH)
      if benchmark is None:
          return None
  
      if isinstance(benchmark, pd.Series):
          return benchmark
      else:
          start_time = benchmark_config.get("start_time", None)
          end_time = benchmark_config.get("end_time", None)
  
          if freq is None:
              raise ValueError("benchmark freq can't be None!")
          _codes = (
              benchmark
              if isinstance(benchmark, (list, dict))
              else [benchmark]
          )
          fields = ["$close/Ref($close,1)-1"]
          _temp_result, _ = get_higher_eq_freq_feature(
              _codes, fields, start_time, end_time, freq=freq
          )
          if len(_temp_result) == 0:
              raise ValueError(
                  f"The benchmark {_codes} does not exist. Please provide the right benchmark"
              )
          return (
              _temp_result.groupby(level="datetime")[
                  _temp_result.columns.tolist()[0]
              ]
              .mean()
              .fillna(0)
          )
  
imports: from __future__ import annotations
  import pathlib
  from collections import OrderedDict
  from typing import Any, Dict, List, Optional, Text, Tuple, Type, Union, cast
  import numpy
  import pandas
  import qlib.utils.index_data
  from qlib.backtest.decision import BaseTradeDecision, Order, OrderDir
  from qlib.backtest.exchange import Exchange
  from ..tests.config import CSI300_BENCH
  from ..utils.resam import get_higher_eq_freq_feature, resam_ts_data
  from .high_performance_ds import BaseOrderIndicator, BaseSingleMetric, NumpyOrderIndicator
label_desc: Use image node_id 4 for calling the PortfolioMetrics obj's underlying member method code with example usage: obj._cal_benchmark(benchmark_config, freq) and returns: None, None, benchmark, _temp_result