'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.'

def _active_contract(self, oc, front, back, dt):

    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 (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
    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
