def donchian(high, low, lower_length=None, upper_length=None, offset=None, **kwargs):
    'Indicator: Donchian Channels (DC)'
    high = verify_series(high)
    low = verify_series(low)
    lower_length = (int(lower_length) if (lower_length and (lower_length > 0)) else 20)
    upper_length = (int(upper_length) if (upper_length and (upper_length > 0)) else 20)
    lower_min_periods = (int(kwargs['lower_min_periods']) if (('lower_min_periods' in kwargs) and (kwargs['lower_min_periods'] is not None)) else lower_length)
    upper_min_periods = (int(kwargs['upper_min_periods']) if (('upper_min_periods' in kwargs) and (kwargs['upper_min_periods'] is not None)) else upper_length)
    offset = get_offset(offset)
    lower = low.rolling(lower_length, min_periods=lower_min_periods).min()
    upper = high.rolling(upper_length, min_periods=upper_min_periods).max()
    mid = (0.5 * (lower + upper))
    if ('fillna' in kwargs):
        lower.fillna(kwargs['fillna'], inplace=True)
        mid.fillna(kwargs['fillna'], inplace=True)
        upper.fillna(kwargs['fillna'], inplace=True)
    if ('fill_method' in kwargs):
        lower.fillna(method=kwargs['fill_method'], inplace=True)
        mid.fillna(method=kwargs['fill_method'], inplace=True)
        upper.fillna(method=kwargs['fill_method'], inplace=True)
    if (offset != 0):
        lower = lower.shift(offset)
        mid = mid.shift(offset)
        upper = upper.shift(offset)
    lower.name = f'DCL_{lower_length}_{upper_length}'
    mid.name = f'DCM_{lower_length}_{upper_length}'
    upper.name = f'DCU_{lower_length}_{upper_length}'
    mid.category = upper.category = lower.category = 'volatility'
    data = {lower.name: lower, mid.name: mid, upper.name: upper}
    dcdf = DataFrame(data)
    dcdf.name = f'DC_{lower_length}_{upper_length}'
    dcdf.category = mid.category
    return dcdf
Indicator: Donchian Channels (DC)
def donchian(high, low, lower_length=None, upper_length=None, offset=None, **kwargs):
    
    high = verify_series(high)
    low = verify_series(low)
    lower_length = (int(lower_length) if (lower_length and (lower_length > 0)) else 20)
    upper_length = (int(upper_length) if (upper_length and (upper_length > 0)) else 20)
    lower_min_periods = (int(kwargs['lower_min_periods']) if (('lower_min_periods' in kwargs) and (kwargs['lower_min_periods'] is not None)) else lower_length)
    upper_min_periods = (int(kwargs['upper_min_periods']) if (('upper_min_periods' in kwargs) and (kwargs['upper_min_periods'] is not None)) else upper_length)
    offset = get_offset(offset)
    lower = low.rolling(lower_length, min_periods=lower_min_periods).min()
    upper = high.rolling(upper_length, min_periods=upper_min_periods).max()
    mid = (0.5 * (lower + upper))
    if ('fillna' in kwargs):
        lower.fillna(kwargs['fillna'], inplace=True)
        mid.fillna(kwargs['fillna'], inplace=True)
        upper.fillna(kwargs['fillna'], inplace=True)
    if ('fill_method' in kwargs):
        lower.fillna(method=kwargs['fill_method'], inplace=True)
        mid.fillna(method=kwargs['fill_method'], inplace=True)
        upper.fillna(method=kwargs['fill_method'], inplace=True)
    if (offset != 0):
        lower = lower.shift(offset)
        mid = mid.shift(offset)
        upper = upper.shift(offset)
    lower.name = f'DCL_{lower_length}_{upper_length}'
    mid.name = f'DCM_{lower_length}_{upper_length}'
    upper.name = f'DCU_{lower_length}_{upper_length}'
    mid.category = upper.category = lower.category = 'volatility'
    data = {lower.name: lower, mid.name: mid, upper.name: upper}
    dcdf = DataFrame(data)
    dcdf.name = f'DC_{lower_length}_{upper_length}'
    dcdf.category = mid.category
    return dcdf