<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _active_contract(self, oc, front, back, dt):
 r""" Return the active contract based on the previous trading day's volume. In the rare case that a double volume switch occurs we treat the first switch as the roll. Take the following case for example: | +++++ _____ | + __ / <--- 'G' | ++/++\++++/++ | _/ \__/ + | / + | ____/ + <--- 'F' |_________|__|___|________ a b c <--- Switches We should treat 'a' as the roll date rather than 'c' because from the perspective of 'a', if a switch happens and we are pretty close to the auto-close date, we would probably assume it is time to roll. This means that for every date after 'a', `data.current(cf, 'contract')` should return the 'G' contract. """

        front_contract = oc.sid_to_contract[front].contract
        back_contract = oc.sid_to_contract[back].contract

        tc = self.trading_calendar
        trading_day = tc.day
        prev = dt - trading_day
        get_value = self.session_reader.get_value

        # If the front contract is past its auto close date it cannot be the
        # active contract, so return the back contract. Similarly, if the back
        # contract has not even started yet, just return the front contract.
        # The reason for using 'prev' to see if the contracts are alive instead
        # of using 'dt' is because we need to get each contract's volume on the
        # previous day, so we need to make sure that each contract exists on
        # 'prev' in order to call 'get_value' below.
        if dt > min(front_contract.auto_close_date, front_contract.end_date):
            return back
        elif front_contract.start_date > prev:
            return back
        elif dt > min(back_contract.auto_close_date, back_contract.end_date):
            return front
        elif back_contract.start_date > prev:
            return front

        front_vol = get_value(front, prev, 'volume')
        back_vol = get_value(back, prev, 'volume')
        if back_vol > front_vol:
            return back

        gap_start = max(
            back_contract.start_date,
            front_contract.auto_close_date - (trading_day * self.GRACE_DAYS),
        )
        gap_end = prev - trading_day
        if dt < gap_start:
            return front

        # If we are within `self.GRACE_DAYS` of the front contract's auto close
        # date, and a volume flip happened during that period, return the back
        # contract as the active one.
        sessions = tc.sessions_in_range(
            tc.minute_to_session_label(gap_start),
            tc.minute_to_session_label(gap_end),
        )
        for session in sessions:
            front_vol = get_value(front, session, 'volume')
            back_vol = get_value(back, session, 'volume')
            if back_vol > front_vol:
                return back
        return front