code: def make_future_info(
      first_sid,
      root_symbols,
      years,
      notice_date_func,
      expiration_date_func,
      start_date_func,
      month_codes=None,
      multiplier=500,
  ):
      """
      Create a DataFrame representing futures for `root_symbols` during `year`.
  
      Generates a contract per triple of (symbol, year, month) supplied to
      `root_symbols`, `years`, and `month_codes`.
  
      Parameters
      ----------
      first_sid : int
          The first sid to use for assigning sids to the created contracts.
      root_symbols : list[str]
          A list of root symbols for which to create futures.
      years : list[int or str]
          Years (e.g. 2014), for which to produce individual contracts.
      notice_date_func : (Timestamp) -> Timestamp
          Function to generate notice dates from first of the month associated
          with asset month code.  Return NaT to simulate futures with no notice
          date.
      expiration_date_func : (Timestamp) -> Timestamp
          Function to generate expiration dates from first of the month
          associated with asset month code.
      start_date_func : (Timestamp) -> Timestamp, optional
          Function to generate start dates from first of the month associated
          with each asset month code.  Defaults to a start_date one year prior
          to the month_code date.
      month_codes : dict[str -> [1..12]], optional
          Dictionary of month codes for which to create contracts.  Entries
          should be strings mapped to values from 1 (January) to 12 (December).
          Default is zipline.futures.CMES_CODE_TO_MONTH
      multiplier : int
          The contract multiplier.
  
      Returns
      -------
      futures_info : pd.DataFrame
          DataFrame of futures data suitable for passing to an AssetDBWriter.
      """
      if month_codes is None:
          month_codes = CMES_CODE_TO_MONTH
  
      year_strs = list(map(str, years))
      years = [pd.Timestamp(s, tz="UTC") for s in year_strs]
  
      # Pairs of string/date like ('K06', 2006-05-01) sorted by year/month
      # `MonthBegin(month_num - 1)` since the year already starts at month 1.
      contract_suffix_to_beginning_of_month = tuple(
          (month_code + year_str[-2:], year + MonthBegin(month_num - 1))
          for ((year, year_str), (month_code, month_num)) in product(
              zip(years, year_strs),
              sorted(
                  list(month_codes.items()), key=lambda item: item[1]
              ),
          )
      )
  
      contracts = []
      parts = product(
          root_symbols, contract_suffix_to_beginning_of_month
      )
      for sid, (root_sym, (suffix, month_begin)) in enumerate(
          parts, first_sid
      ):
          contracts.append(
              {
                  "sid": sid,
                  "root_symbol": root_sym,
                  "symbol": root_sym + suffix,
                  "start_date": start_date_func(month_begin),
                  "notice_date": notice_date_func(month_begin),
                  "expiration_date": expiration_date_func(month_begin),
                  "multiplier": multiplier,
                  "exchange": "TEST",
              }
          )
      return pd.DataFrame.from_records(contracts, index="sid")
  
file_path: zipline/zipline/assets/synthetic.py
imports: from itertools import product
  from string import ascii_uppercase
  import pandas
  from pandas.tseries.offsets import MonthBegin
  from .futures import CMES_CODE_TO_MONTH
label_desc: Use image node_id 5 for calling a global function with example usage: make_future_info(first_sid, root_symbols, years, notice_date_func, expiration_date_func, start_date_func, month_codes, multiplier) and returns: pd