code: def periods_in_range(self, months_per, start_session, end_session):
      one_day = datetime.timedelta(days=1)
      ends = []
      cur_start = start_session.replace(day=1)
  
      # in edge cases (all sids filtered out, start/end are adjacent)
      # a test will not generate any returns data
      if len(self.algorithm_returns) == 0:
          return ends
  
      # ensure that we have an end at the end of a calendar month, in case
      # the return series ends mid-month...
      the_end = (
          end_session.replace(day=1) + relativedelta(months=1) - one_day
      )
      while True:
          cur_end = (
              cur_start + relativedelta(months=months_per) - one_day
          )
          if cur_end > the_end:
              break
          cur_period_metrics = RiskMetricsPeriod(
              start_session=cur_start,
              end_session=cur_end,
              returns=self.algorithm_returns,
              benchmark_returns=self.benchmark_returns,
              trading_calendar=self.trading_calendar,
              treasury_curves=self.treasury_curves,
              algorithm_leverages=self.algorithm_leverages,
          )
  
          ends.append(cur_period_metrics)
          cur_start = cur_start + relativedelta(months=1)
  
      return ends
  
file_path: catalyst/catalyst/finance/risk/report.py
imports: import logbook
  import datetime
  from dateutil.relativedelta import relativedelta
  from .period import RiskMetricsPeriod
  from catalyst.constants import LOG_LEVEL
label_desc: Use image node_id 3 for calling the RiskReport obj's underlying member method code with example usage: obj.periods_in_range(months_per, start_session, end_session) and returns: ends, ends