code: def compute_ma(
      data: SERIES_OR_DATAFRAME,
      fun: Callable[[SERIES_OR_DATAFRAME, int], pd.Series],
      spans: List[int],
      plot: bool = True,
  ) -> pd.DataFrame:
      """Computes a band of moving averages (sma or ema, depends on the input argument
      `fun`) for a number of different time windows. If `plot` is `True`, it also
      computes and sets markers for buy/sell signals based on crossovers of the Moving
      Averages with the shortest/longest spans.
  
      :param data: A series/dataframe of daily stock prices (if DataFrame,
          only one column is expected)
      :type data: :py:data:`~.finquant.data_types.SERIES_OR_DATAFRAME`
      :param fun: Function that computes a moving average, e.g. ```sma``` (simple) or
           ```ema``` (exponential).
      :param spans: List of integers, time windows to compute the Moving Average on.
      :param plot: boolean, whether to plot the moving averages
           and buy/sell signals based on crossovers of shortest and longest
           moving average, or not, default: True
  
      :return: Moving averages of given data.
      """
      # Type validations:
      type_validation(data=data, fun=fun, spans=spans, plot=plot)
      m_a = data.copy(deep=True)
      # converting data to pd.DataFrame if it is a pd.Series (for subsequent function calls):
      if isinstance(m_a, pd.Series):
          m_a = m_a.to_frame()
      # compute moving averages
      for span in spans:
          m_a[str(span) + "d"] = fun(data, span)
      if plot:
          fig = plt.figure()
          axis = fig.add_subplot(111)
          # plot moving averages
          m_a.plot(ax=axis)
          # Create buy/sell signals of shortest and longest span
          minspan = min(spans)
          minlabel = str(minspan) + "d"
          maxspan = max(spans)
          maxlabel = str(maxspan) + "d"
          signals = m_a.copy(deep=True)
          signals["diff"] = 0.0
          signals["diff"][minspan:] = np.where(
              m_a[minlabel][minspan:] > m_a[maxlabel][minspan:],
              1.0,
              0.0,
          )
          # Generate trading orders
          signals["signal"] = signals["diff"].diff()
          # marker for buy signal
          axis.plot(
              signals.loc[signals["signal"] == 1.0].index.values,
              signals[minlabel][signals["signal"] == 1.0].values,
              marker="^",
              markersize=10,
              color="r",
              label="buy signal",
          )
          # marker for sell signal
          axis.plot(
              signals.loc[signals["signal"] == -1.0].index.values,
              signals[minlabel][signals["signal"] == -1.0].values,
              marker="v",
              markersize=10,
              color="b",
              label="sell signal",
          )
          # title
          title = "Band of Moving Averages (" + str(fun.__name__) + ")"
          plt.title(title)
          # legend
          plt.legend(ncol=2)
          # axis labels
          plt.xlabel(data.index.name)
          plt.ylabel("Price")
      return m_a
  
file_path: FinQuant/finquant/moving_average.py
imports: from typing import Callable, List
  import matplotlib.pyplot
  import numpy
  import pandas
  from finquant.data_types import SERIES_OR_DATAFRAME
  from finquant.type_utilities import type_validation
label_desc: Use image node_id 1 for calling a global function with example usage: compute_ma(data, fun, spans, plot) and returns: m_a