class_docstr: Construct total return (spot) indices for FX. In future will also convert assets from local currency to foreign currency
  denomination and construct indices from forwards series.
class_docstr_tok: ["Construct","total","return","(","spot",")","indices","for","FX",".","In","future","will","also","convert","assets","from","local","currency","to","foreign","currency","denomination","and","construct","indices","from","forwards","series","."]
docstr: Creates total return index for selected FX crosses from spot and deposit data
  
  Parameters
  ----------
  cross_fx : String
      Crosses to construct total return indices (can be a list)
  tenor : String
      Tenor of deposit rates to use to compute carry (typically ON for spot)
  spot_df : pd.DataFrame
      Spot data (must include crosses we select)
  deposit_df : pd.DataFrame
      Deposit data
  
  Returns
  -------
  pd.DataFrame
docstr_tok: ["Creates","total","return","index","for","selected","FX","crosses","from","spot","and","deposit","data","Parameters","--","--","--","--","--","cross_fx",":","String","Crosses","to","construct","total","return","indices","(","can","be","a","list",")","tenor",":","String","Tenor","of","deposit","rates","to","use","to","compute","carry","(","typically","ON","for","spot",")","spot_df",":","pd.DataFrame","Spot","data","(","must","include","crosses","we","select",")","deposit_df",":","pd.DataFrame","Deposit","data","Returns","--","--","--","-","pd.DataFrame"]
code: def construct_total_return_index(
      self,
      cross_fx,
      market_df,
      depo_tenor=None,
      output_calculation_fields=None,
      field=None,
  ):
      """Creates total return index for selected FX crosses from spot and deposit data
  
      Parameters
      ----------
      cross_fx : String
          Crosses to construct total return indices (can be a list)
      tenor : String
          Tenor of deposit rates to use to compute carry (typically ON for spot)
      spot_df : pd.DataFrame
          Spot data (must include crosses we select)
      deposit_df : pd.DataFrame
          Deposit data
  
      Returns
      -------
      pd.DataFrame
      """
      if not (isinstance(cross_fx, list)):
          cross_fx = [cross_fx]
  
      if depo_tenor is None:
          depo_tenor = self._depo_tenor
      if output_calculation_fields is None:
          output_calculation_fields = self._output_calculation_fields
      if field is None:
          field = self._field
  
      total_return_index_df_agg = []
  
      for cross in cross_fx:
          # Get the spot series, base deposit
          base_deposit = market_df[
              cross[0:3] + depo_tenor + "." + field
          ].to_frame()
          terms_deposit = market_df[
              cross[3:6] + depo_tenor + "." + field
          ].to_frame()
  
          # Eg. if we specify USDUSD
          if cross[0:3] == cross[3:6]:
              total_return_index_df_agg.append(
                  pd.DataFrame(
                      100,
                      index=base_deposit.index,
                      columns=[cross + "-tot.close"],
                  )
              )
          else:
              carry = base_deposit.join(terms_deposit, how="inner")
  
              spot = market_df[cross + "." + field].to_frame()
  
              base_daycount = self.get_day_count_conv(cross[0:3])
              terms_daycount = self.get_day_count_conv(cross[4:6])
  
              # Align the base & terms deposits series to spot (this should already be done by construction)
              # spot, carry = spot.align(carry, join='left', axis=0)
  
              # Sometimes depo data can be patchy, ok to fill down, given not very volatile (don't do this with spot!)
              carry = carry.fillna(method="ffill") / 100.0
  
              # In case there are values missing at start of list (fudge for old data!)
              carry = carry.fillna(method="bfill")
  
              spot = spot[cross + "." + field].to_frame()
  
              spot_vals = spot[cross + "." + field].values
              base_deposit_vals = carry[
                  cross[0:3] + depo_tenor + "." + field
              ].values
              terms_deposit_vals = carry[
                  cross[3:6] + depo_tenor + "." + field
              ].values
  
              # Calculate the time difference between each data point (flooring it to whole days, because carry
              # is accured when there's a new day)
              spot["index_col"] = spot.index.floor("D")
              time = spot["index_col"].diff()
              spot = spot.drop("index_col", 1)
  
              time_diff = (
                  time.values.astype(float) / 86400000000000.0
              )  # get time difference in days
              time_diff[0] = 0.0
  
              # Use Numba to do total return index calculation given has many loops
              total_return_index_df = pd.DataFrame(
                  index=spot.index,
                  columns=[cross + "-tot.close"],
                  data=_spot_index_numba(
                      spot_vals,
                      time_diff,
                      base_deposit_vals,
                      terms_deposit_vals,
                      base_daycount,
                      terms_daycount,
                  ),
              )
  
              if output_calculation_fields:
                  total_return_index_df[
                      cross + "-carry." + field
                  ] = carry
                  total_return_index_df[
                      cross + "-tot-return." + field
                  ] = (
                      total_return_index_df
                      / total_return_index_df.shift(1)
                      - 1.0
                  )
                  total_return_index_df[
                      cross + "-spot-return." + field
                  ] = (spot / spot.shift(1) - 1.0)
  
              total_return_index_df_agg.append(total_return_index_df)
  
      return self._calculations.join(
          total_return_index_df_agg, how="outer"
      )
  
file_path: finmarketpy/finmarketpy/curve/fxspotcurve.py
imports: import pandas
  from numba import guvectorize
  from findatapy.market import Market, MarketDataRequest
  from findatapy.timeseries import Calculations
  from finmarketpy.util.marketconstants import MarketConstants
label_desc: Use image node_id 7 for calling the FXSpotCurve obj's underlying member method code with example usage: obj.construct_total_return_index(cross_fx, market_df, depo_tenor, output_calculation_fields, field) and returns: self