'Get the rolls, i.e. the session at which to hop from contract to
contract in the chain.
Parameters
root_symbol : str
The root symbol for which to calculate rolls.
start : Timestamp
Start of the date range.
end : Timestamp
End of the date range.
offset : int
Offset from the primary.
Returns
rolls - list[tuple(sid, roll_date)]
A list of rolls, where first value is the first active `sid`,
and the `roll_date` on which to hop to the next contract.
The last pair in the chain has a value of `None` since the roll
is after the range.'

def get_rolls(self, root_symbol, start, end, offset):

    oc = self.asset_finder.get_ordered_contracts(root_symbol)
    front = self.get_contract_center(root_symbol, end, 0)
    back = oc.contract_at_offset(front, 1, end.value)
    if (back is not None):
        end_session = self.trading_calendar.minute_to_session_label(end)
        first = self._active_contract(oc, front, back, end_session)
    else:
        first = front
    first_contract = oc.sid_to_contract[first]
    rolls = [((first_contract >> offset).contract.sid, None)]
    tc = self.trading_calendar
    sessions = tc.sessions_in_range(tc.minute_to_session_label(start), tc.minute_to_session_label(end))
    freq = sessions.freq
    if (first == front):
        curr = (first_contract << 1)
    else:
        curr = (first_contract << 2)
    session = sessions[(-1)]
    while ((session > start) and (curr is not None)):
        front = curr.contract.sid
        back = rolls[0][0]
        prev_c = curr.prev
        while (session > start):
            prev = (session - freq)
            if (prev_c is not None):
                if (prev < prev_c.contract.auto_close_date):
                    break
            if (back != self._active_contract(oc, front, back, prev)):
                rolls.insert(0, ((curr >> offset).contract.sid, session))
                break
            session = prev
        curr = curr.prev
        if (curr is not None):
            session = (curr.contract.auto_close_date + freq)
    return rolls
