首页 > 编程语言 >PandasTA 源码解析(十七)

PandasTA 源码解析(十七)

时间:2024-04-15 13:56:29浏览次数:24  
标签:PandasTA kwargs volume length 源码 offset close fillna 解析

.\pandas-ta\pandas_ta\volume\adosc.py

# -*- coding: utf-8 -*-
# 导入 ad 模块
from .ad import ad
# 从 pandas_ta 库中导入 Imports 模块
from pandas_ta import Imports
# 从 pandas_ta.overlap 模块中导入 ema 函数
from pandas_ta.overlap import ema
# 从 pandas_ta.utils 模块中导入 get_offset 和 verify_series 函数
from pandas_ta.utils import get_offset, verify_series

# 定义 adosc 函数,用于计算累积/分布振荡器指标
def adosc(high, low, close, volume, open_=None, fast=None, slow=None, talib=None, offset=None, **kwargs):
    """Indicator: Accumulation/Distribution Oscillator"""
    # 验证参数有效性
    # 如果 fast 参数存在且大于 0,则将其转换为整数类型,否则设为默认值 3
    fast = int(fast) if fast and fast > 0 else 3
    # 如果 slow 参数存在且大于 0,则将其转换为整数类型,否则设为默认值 10
    slow = int(slow) if slow and slow > 0 else 10
    # 计算 _length,即 fast 和 slow 中的较大值
    _length = max(fast, slow)
    # 验证 high、low、close、volume 系列数据的长度,使其与 _length 相同
    high = verify_series(high, _length)
    low = verify_series(low, _length)
    close = verify_series(close, _length)
    volume = verify_series(volume, _length)
    # 获取偏移量,根据 offset 参数
    offset = get_offset(offset)
    # 如果 kwargs 中存在 "length" 键,则将其移除
    if "length" in kwargs: kwargs.pop("length")
    # 如果 talib 参数为布尔类型且为真,则将 mode_tal 设为 True,否则设为 False
    mode_tal = bool(talib) if isinstance(talib, bool) else True

    # 如果 high、low、close、volume 中存在空值,则返回空值
    if high is None or low is None or close is None or volume is None: return

    # 计算结果
    if Imports["talib"] and mode_tal:
        # 如果导入了 TA Lib 并且 mode_tal 为 True,则使用 TA Lib 计算 adosc
        from talib import ADOSC
        adosc = ADOSC(high, low, close, volume, fast, slow)
    else:
        # 否则,使用自定义的 ad 函数计算 ad_,然后分别计算其快速和慢速移动平均线
        ad_ = ad(high=high, low=low, close=close, volume=volume, open_=open_)
        fast_ad = ema(close=ad_, length=fast, **kwargs)
        slow_ad = ema(close=ad_, length=slow, **kwargs)
        adosc = fast_ad - slow_ad

    # 根据偏移量对结果进行偏移
    if offset != 0:
        adosc = adosc.shift(offset)

    # 处理填充值
    if "fillna" in kwargs:
        adosc.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        adosc.fillna(method=kwargs["fill_method"], inplace=True)

    # 设置指标名称和类别
    adosc.name = f"ADOSC_{fast}_{slow}"
    adosc.category = "volume"

    # 返回计算结果
    return adosc


# 设置 adosc 函数的文档字符串
adosc.__doc__ = \
"""Accumulation/Distribution Oscillator or Chaikin Oscillator

Accumulation/Distribution Oscillator indicator utilizes
Accumulation/Distribution and treats it similarily to MACD
or APO.

Sources:
    https://www.investopedia.com/articles/active-trading/031914/understanding-chaikin-oscillator.asp

Calculation:
    Default Inputs:
        fast=12, slow=26
    AD = Accum/Dist
    ad = AD(high, low, close, open)
    fast_ad = EMA(ad, fast)
    slow_ad = EMA(ad, slow)
    ADOSC = fast_ad - slow_ad

Args:
    high (pd.Series): Series of 'high's
    low (pd.Series): Series of 'low's
    close (pd.Series): Series of 'close's
    open (pd.Series): Series of 'open's
    volume (pd.Series): Series of 'volume's
    fast (int): The short period. Default: 12
    slow (int): The long period. Default: 26
    talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib
        version. Default: True
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""

.\pandas-ta\pandas_ta\volume\aobv.py

# -*- coding: utf-8 -*-
# 从 pandas 库中导入 DataFrame 类
from pandas import DataFrame
# 从当前目录下的 obv 模块中导入 obv 函数
from .obv import obv
# 从 pandas_ta.overlap 模块中导入 ma 函数
from pandas_ta.overlap import ma
# 从 pandas_ta.trend 模块中导入 long_run 和 short_run 函数
from pandas_ta.trend import long_run, short_run
# 从 pandas_ta.utils 模块中导入 get_offset 和 verify_series 函数
from pandas_ta.utils import get_offset, verify_series

# 定义名为 aobv 的函数,计算 Archer On Balance Volume (AOBV) 指标
def aobv(close, volume, fast=None, slow=None, max_lookback=None, min_lookback=None, mamode=None, offset=None, **kwargs):
    """Indicator: Archer On Balance Volume (AOBV)"""
    # 验证参数
    # 如果 fast 存在且大于 0,则将其转换为整数,否则设为默认值 4
    fast = int(fast) if fast and fast > 0 else 4
    # 如果 slow 存在且大于 0,则将其转换为整数,否则设为默认值 12
    slow = int(slow) if slow and slow > 0 else 12
    # 如果 max_lookback 存在且大于 0,则将其转换为整数,否则设为默认值 2
    max_lookback = int(max_lookback) if max_lookback and max_lookback > 0 else 2
    # 如果 min_lookback 存在且大于 0,则将其转换为整数,否则设为默认值 2
    min_lookback = int(min_lookback) if min_lookback and min_lookback > 0 else 2
    # 如果 slow 小于 fast,则交换它们的值
    if slow < fast:
        fast, slow = slow, fast
    # 如果 mamode 不是字符串类型,则设为默认值 "ema"
    mamode = mamode if isinstance(mamode, str) else "ema"
    # 计算需要处理的数据长度
    _length = max(fast, slow, max_lookback, min_lookback)
    # 验证 close 和 volume 是否为有效的数据序列,长度为 _length
    close = verify_series(close, _length)
    volume = verify_series(volume, _length)
    # 获取偏移量
    offset = get_offset(offset)
    # 如果 kwargs 中存在 "length" 键,则将其移除
    if "length" in kwargs: kwargs.pop("length")
    # 从 kwargs 中获取 "run_length" 键的值,如果不存在则设为默认值 2
    run_length = kwargs.pop("run_length", 2)

    # 如果 close 或 volume 为 None,则返回空
    if close is None or volume is None: return

    # 计算结果
    # 计算 On Balance Volume(OBV)
    obv_ = obv(close=close, volume=volume, **kwargs)
    # 计算 OBV 的快速移动平均线
    maf = ma(mamode, obv_, length=fast, **kwargs)
    # 计算 OBV 的慢速移动平均线
    mas = ma(mamode, obv_, length=slow, **kwargs)

    # 当快速和慢速移动平均线长度为指定长度时
    obv_long = long_run(maf, mas, length=run_length)
    obv_short = short_run(maf, mas, length=run_length)

    # 考虑偏移量
    if offset != 0:
        obv_ = obv_.shift(offset)
        maf = maf.shift(offset)
        mas = mas.shift(offset)
        obv_long = obv_long.shift(offset)
        obv_short = obv_short.shift(offset)

    # 处理填充值
    if "fillna" in kwargs:
        obv_.fillna(kwargs["fillna"], inplace=True)
        maf.fillna(kwargs["fillna"], inplace=True)
        mas.fillna(kwargs["fillna"], inplace=True)
        obv_long.fillna(kwargs["fillna"], inplace=True)
        obv_short.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        obv_.fillna(method=kwargs["fill_method"], inplace=True)
        maf.fillna(method=kwargs["fill_method"], inplace=True)
        mas.fillna(method=kwargs["fill_method"], inplace=True)
        obv_long.fillna(method=kwargs["fill_method"], inplace=True)
        obv_short.fillna(method=kwargs["fill_method"], inplace=True)

    # 准备返回的 DataFrame
    _mode = mamode.lower()[0] if len(mamode) else ""
    data = {
        obv_.name: obv_,
        f"OBV_min_{min_lookback}": obv_.rolling(min_lookback).min(),
        f"OBV_max_{max_lookback}": obv_.rolling(max_lookback).max(),
        f"OBV{_mode}_{fast}": maf,
        f"OBV{_mode}_{slow}": mas,
        f"AOBV_LR_{run_length}": obv_long,
        f"AOBV_SR_{run_length}": obv_short,
    }
    # 创建 DataFrame
    aobvdf = DataFrame(data)

    # 给 DataFrame 命名并分类
    aobvdf.name = f"AOBV{_mode}_{fast}_{slow}_{min_lookback}_{max_lookback}_{run_length}"
    aobvdf.category = "volume"

    return aobvdf

.\pandas-ta\pandas_ta\volume\cmf.py

# -*- coding: utf-8 -*-

# 从 pandas_ta.utils 导入一些必要的函数
from pandas_ta.utils import get_offset, non_zero_range, verify_series

# 定义 CMF 函数,计算 Chaikin Money Flow 指标
def cmf(high, low, close, volume, open_=None, length=None, offset=None, **kwargs):
    """Indicator: Chaikin Money Flow (CMF)"""
    # 验证参数
    # 确保 length 是整数且大于 0,若未指定则默认为 20
    length = int(length) if length and length > 0 else 20
    # 最小期数为 length 或者 kwargs 中 min_periods 的值,若未指定则为 length
    min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
    # 取 length 和 min_periods 中的较大值作为真正的 length
    _length = max(length, min_periods)
    # 确保传入的数据是合法的 Series 类型,长度为 _length
    high = verify_series(high, _length)
    low = verify_series(low, _length)
    close = verify_series(close, _length)
    volume = verify_series(volume, _length)
    # 获取偏移量
    offset = get_offset(offset)

    # 若传入的数据有缺失,则返回 None
    if high is None or low is None or close is None or volume is None: return

    # 计算结果
    if open_ is not None:
        # 若存在开盘价数据,则使用开盘价计算 AD
        open_ = verify_series(open_)
        ad = non_zero_range(close, open_)  # 使用开盘价计算 AD
    else:
        # 若不存在开盘价数据,则使用高、低、收盘价计算 AD
        ad = 2 * close - (high + low)  # 使用高、低、收盘价计算 AD

    # 计算 CMF
    ad *= volume / non_zero_range(high, low)
    cmf = ad.rolling(length, min_periods=min_periods).sum()
    cmf /= volume.rolling(length, min_periods=min_periods).sum()

    # 偏移结果
    if offset != 0:
        cmf = cmf.shift(offset)

    # 处理填充值
    if "fillna" in kwargs:
        cmf.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        cmf.fillna(method=kwargs["fill_method"], inplace=True)

    # 命名并分类
    cmf.name = f"CMF_{length}"
    cmf.category = "volume"

    # 返回结果
    return cmf

# 设置 CMF 函数的文档字符串
cmf.__doc__ = \
"""Chaikin Money Flow (CMF)

Chailin Money Flow measures the amount of money flow volume over a specific
period in conjunction with Accumulation/Distribution.

Sources:
    https://www.tradingview.com/wiki/Chaikin_Money_Flow_(CMF)
    https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:chaikin_money_flow_cmf

Calculation:
    Default Inputs:
        length=20
    if 'open':
        ad = close - open
    else:
        ad = 2 * close - high - low

    hl_range = high - low
    ad = ad * volume / hl_range
    CMF = SUM(ad, length) / SUM(volume, length)

Args:
    high (pd.Series): Series of 'high's
    low (pd.Series): Series of 'low's
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    open_ (pd.Series): Series of 'open's. Default: None
    length (int): The short period. Default: 20
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""

.\pandas-ta\pandas_ta\volume\efi.py

# -*- coding: utf-8 -*-
# 从 pandas_ta.overlap 模块导入 ma 函数
from pandas_ta.overlap import ma
# 从 pandas_ta.utils 模块导入 get_drift、get_offset、verify_series 函数
from pandas_ta.utils import get_drift, get_offset, verify_series


# 定义 EFI 函数,计算 Elder's Force Index (EFI)
def efi(close, volume, length=None, mamode=None, drift=None, offset=None, **kwargs):
    """Indicator: Elder's Force Index (EFI)"""
    # 验证参数
    # 将 length 转换为整数,如果未提供或小于等于 0,则设为默认值 13
    length = int(length) if length and length > 0 else 13
    # 如果未提供 mamode 或不是字符串,则设为默认值 'ema'
    mamode = mamode if isinstance(mamode, str) else "ema"
    # 验证 close 和 volume 是否为有效序列,长度为 length
    close = verify_series(close, length)
    volume = verify_series(volume, length)
    # 获取漂移和偏移量
    drift = get_drift(drift)
    offset = get_offset(offset)

    # 如果 close 或 volume 为空,则返回空
    if close is None or volume is None: return

    # 计算结果
    # 计算价格和成交量的差值,再乘以漂移量
    pv_diff = close.diff(drift) * volume
    # 计算 EFI,使用指定的移动平均模式和长度
    efi = ma(mamode, pv_diff, length=length)

    # 偏移
    # 如果偏移量不为零,则对 EFI 进行偏移
    if offset != 0:
        efi = efi.shift(offset)

    # 处理填充
    # 如果 kwargs 中包含 'fillna',则用指定值填充 EFI 的缺失值
    if "fillna" in kwargs:
        efi.fillna(kwargs["fillna"], inplace=True)
    # 如果 kwargs 中包含 'fill_method',则使用指定的填充方法填充 EFI 的缺失值
    if "fill_method" in kwargs:
        efi.fillna(method=kwargs["fill_method"], inplace=True)

    # 设置名称和分类
    # 将 EFI 的名称设为字符串模板 "EFI_{length}"
    efi.name = f"EFI_{length}"
    # 将 EFI 的分类设为 "volume"
    efi.category = "volume"

    # 返回 EFI
    return efi


# 设置 EFI 函数的文档字符串
efi.__doc__ = \
"""Elder's Force Index (EFI)

Elder's Force Index measures the power behind a price movement using price
and volume as well as potential reversals and price corrections.

Sources:
    https://www.tradingview.com/wiki/Elder%27s_Force_Index_(EFI)
    https://www.motivewave.com/studies/elders_force_index.htm

Calculation:
    Default Inputs:
        length=20, drift=1, mamode=None
    EMA = Exponential Moving Average
    SMA = Simple Moving Average

    pv_diff = close.diff(drift) * volume
    if mamode == 'sma':
        EFI = SMA(pv_diff, length)
    else:
        EFI = EMA(pv_diff, length)

Args:
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    length (int): The short period. Default: 13
    drift (int): The diff period. Default: 1
    mamode (str): See ```help(ta.ma)```py. Default: 'ema'
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""

.\pandas-ta\pandas_ta\volume\eom.py

# -*- coding: utf-8 -*-
# 导入需要的库
from pandas_ta.overlap import hl2, sma
from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series

# 定义 Ease of Movement (EOM) 函数
def eom(high, low, close, volume, length=None, divisor=None, drift=None, offset=None, **kwargs):
    """Indicator: Ease of Movement (EOM)"""
    # 验证参数
    length = int(length) if length and length > 0 else 14
    divisor = divisor if divisor and divisor > 0 else 100000000
    high = verify_series(high, length)
    low = verify_series(low, length)
    close = verify_series(close, length)
    volume = verify_series(volume, length)
    drift = get_drift(drift)
    offset = get_offset(offset)

    # 如果任何一个输入序列为 None,则返回 None
    if high is None or low is None or close is None or volume is None: return

    # 计算结果
    # 计算高低价范围
    high_low_range = non_zero_range(high, low)
    # 计算距离
    distance  = hl2(high=high, low=low)
    distance -= hl2(high=high.shift(drift), low=low.shift(drift))
    # 计算箱比率
    box_ratio = volume / divisor
    box_ratio /= high_low_range
    # 计算 EOM
    eom = distance / box_ratio
    # 对 EOM 序列进行简单移动平均
    eom = sma(eom, length=length)

    # 偏移
    if offset != 0:
        eom = eom.shift(offset)

    # 处理填充
    if "fillna" in kwargs:
        eom.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        eom.fillna(method=kwargs["fill_method"], inplace=True)

    # 设置名称和类别
    eom.name = f"EOM_{length}_{divisor}"
    eom.category = "volume"

    return eom


# 设置 EOM 函数的文档字符串
eom.__doc__ = \
"""Ease of Movement (EOM)

Ease of Movement is a volume based oscillator that is designed to measure the
relationship between price and volume flucuating across a zero line.

Sources:
    https://www.tradingview.com/wiki/Ease_of_Movement_(EOM)
    https://www.motivewave.com/studies/ease_of_movement.htm
    https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:ease_of_movement_emv

Calculation:
    Default Inputs:
        length=14, divisor=100000000, drift=1
    SMA = Simple Moving Average
    hl_range = high - low
    distance = 0.5 * (high - high.shift(drift) + low - low.shift(drift))
    box_ratio = (volume / divisor) / hl_range
    eom = distance / box_ratio
    EOM = SMA(eom, length)

Args:
    high (pd.Series): Series of 'high's
    low (pd.Series): Series of 'low's
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    length (int): The short period. Default: 14
    drift (int): The diff period. Default: 1
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""

.\pandas-ta\pandas_ta\volume\kvo.py

# 设置文件编码为 UTF-8
# 导入 DataFrame 类
from pandas import DataFrame
# 从 pandas_ta.overlap 模块导入 hlc3 和 ma 函数
from pandas_ta.overlap import hlc3, ma
# 从 pandas_ta.utils 模块导入 get_drift, get_offset, signed_series, verify_series 函数
from pandas_ta.utils import get_drift, get_offset, signed_series, verify_series


# 定义 Klinger Volume Oscillator (KVO) 指标函数
def kvo(high, low, close, volume, fast=None, slow=None, signal=None, mamode=None, drift=None, offset=None, **kwargs):
    """Indicator: Klinger Volume Oscillator (KVO)"""
    # 验证参数
    # 如果 fast 存在且大于 0,则将其转换为整数;否则默认为 34
    fast = int(fast) if fast and fast > 0 else 34
    # 如果 slow 存在且大于 0,则将其转换为整数;否则默认为 55
    slow = int(slow) if slow and slow > 0 else 55
    # 如果 signal 存在且大于 0,则将其转换为整数;否则默认为 13
    signal = int(signal) if signal and signal > 0 else 13
    # 如果 mamode 存在且是字符串类型,则将其转换为小写;否则默认为 'ema'
    mamode = mamode.lower() if mamode and isinstance(mamode, str) else "ema"
    # 计算参数中最大的长度
    _length = max(fast, slow, signal)
    # 验证输入序列的长度
    high = verify_series(high, _length)
    low = verify_series(low, _length)
    close = verify_series(close, _length)
    volume = verify_series(volume, _length)
    # 获取漂移值
    drift = get_drift(drift)
    # 获取偏移值
    offset = get_offset(offset)

    # 如果输入的 high、low、close、volume 有任何一个为 None,则返回 None
    if high is None or low is None or close is None or volume is None: return

    # 计算结果
    # 计算带符号的成交量
    signed_volume = volume * signed_series(hlc3(high, low, close), 1)
    # 从第一个有效索引开始取值
    sv = signed_volume.loc[signed_volume.first_valid_index():,]
    # 计算 KVO 指标
    kvo = ma(mamode, sv, length=fast) - ma(mamode, sv, length=slow)
    # 计算 KVO 的信号线
    kvo_signal = ma(mamode, kvo.loc[kvo.first_valid_index():,], length=signal)

    # 调整偏移
    if offset != 0:
        kvo = kvo.shift(offset)
        kvo_signal = kvo_signal.shift(offset)

    # 处理填充值
    if "fillna" in kwargs:
        kvo.fillna(kwargs["fillna"], inplace=True)
        kvo_signal.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        kvo.fillna(method=kwargs["fill_method"], inplace=True)
        kvo_signal.fillna(method=kwargs["fill_method"], inplace=True)

    # 设置指标的名称和分类
    _props = f"_{fast}_{slow}_{signal}"
    kvo.name = f"KVO{_props}"
    kvo_signal.name = f"KVOs{_props}"
    kvo.category = kvo_signal.category = "volume"

    # 准备返回的 DataFrame
    data = {kvo.name: kvo, kvo_signal.name: kvo_signal}
    df = DataFrame(data)
    df.name = f"KVO{_props}"
    df.category = kvo.category

    return df


# 设置函数文档字符串
kvo.__doc__ = \
"""Klinger Volume Oscillator (KVO)

This indicator was developed by Stephen J. Klinger. It is designed to predict
price reversals in a market by comparing volume to price.

Sources:
    https://www.investopedia.com/terms/k/klingeroscillator.asp
    https://www.daytrading.com/klinger-volume-oscillator

Calculation:
    Default Inputs:
        fast=34, slow=55, signal=13, drift=1
    EMA = Exponential Moving Average

    SV = volume * signed_series(HLC3, 1)
    KVO = EMA(SV, fast) - EMA(SV, slow)
    Signal = EMA(KVO, signal)

Args:
    high (pd.Series): Series of 'high's
    low (pd.Series): Series of 'low's
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    fast (int): The fast period. Default: 34
    long (int): The long period. Default: 55
    length_sig (int): The signal period. Default: 13
    mamode (str): See ```help(ta.ma)```py. Default: 'ema'

"""
    offset (int): How many periods to offset the result. Default: 0

# 偏移量(int):结果要偏移的周期数。默认值为0。
# 参数说明部分,描述函数的参数和返回值
Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method
Returns:
    pd.DataFrame: KVO and Signal columns.

.\pandas-ta\pandas_ta\volume\mfi.py

# -*- coding: utf-8 -*-

# 从 pandas 库中导入 DataFrame 类
from pandas import DataFrame
# 从 pandas_ta 库中导入 Imports 模块
from pandas_ta import Imports
# 从 pandas_ta.overlap 模块中导入 hlc3 函数
from pandas_ta.overlap import hlc3
# 从 pandas_ta.utils 模块中导入 get_drift, get_offset, verify_series 函数
from pandas_ta.utils import get_drift, get_offset, verify_series

# 定义 Money Flow Index (MFI) 函数
def mfi(high, low, close, volume, length=None, talib=None, drift=None, offset=None, **kwargs):
    """Indicator: Money Flow Index (MFI)"""

    # 验证参数
    length = int(length) if length and length > 0 else 14
    high = verify_series(high, length)
    low = verify_series(low, length)
    close = verify_series(close, length)
    volume = verify_series(volume, length)
    drift = get_drift(drift)
    offset = get_offset(offset)
    mode_tal = bool(talib) if isinstance(talib, bool) else True

    # 如果任何一个输入序列为空,则返回空值
    if high is None or low is None or close is None or volume is None: return

    # 计算结果
    if Imports["talib"] and mode_tal:
        # 如果 TA Lib 已安装且 talib 参数为 True,则使用 TA Lib 实现的 MFI 函数计算结果
        from talib import MFI
        mfi = MFI(high, low, close, volume, length)
    else:
        # 否则,使用自定义方法计算 MFI 指标

        # 计算典型价格和原始资金流
        typical_price = hlc3(high=high, low=low, close=close)
        raw_money_flow = typical_price * volume

        # 创建包含不同情况的数据框
        tdf = DataFrame({"diff": 0, "rmf": raw_money_flow, "+mf": 0, "-mf": 0})

        # 根据典型价格的变化情况更新数据框中的不同列
        tdf.loc[(typical_price.diff(drift) > 0), "diff"] = 1
        tdf.loc[tdf["diff"] == 1, "+mf"] = raw_money_flow
        tdf.loc[(typical_price.diff(drift) < 0), "diff"] = -1
        tdf.loc[tdf["diff"] == -1, "-mf"] = raw_money_flow

        # 计算正和负资金流的滚动和
        psum = tdf["+mf"].rolling(length).sum()
        nsum = tdf["-mf"].rolling(length).sum()

        # 计算资金流比率和 MFI 指标
        tdf["mr"] = psum / nsum
        mfi = 100 * psum / (psum + nsum)
        tdf["mfi"] = mfi

    # 偏移
    if offset != 0:
        mfi = mfi.shift(offset)

    # 处理填充
    if "fillna" in kwargs:
        mfi.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        mfi.fillna(method=kwargs["fill_method"], inplace=True)

    # 设置名称和分类
    mfi.name = f"MFI_{length}"
    mfi.category = "volume"

    return mfi

# 设置 MFI 函数的文档字符串
mfi.__doc__ = \
"""Money Flow Index (MFI)

Money Flow Index is an oscillator indicator that is used to measure buying and
selling pressure by utilizing both price and volume.

Sources:
    https://www.tradingview.com/wiki/Money_Flow_(MFI)

Calculation:
    Default Inputs:
        length=14, drift=1
    tp = typical_price = hlc3 = (high + low + close) / 3
    rmf = raw_money_flow = tp * volume

    pmf = pos_money_flow = SUM(rmf, length) if tp.diff(drift) > 0 else 0
    nmf = neg_money_flow = SUM(rmf, length) if tp.diff(drift) < 0 else 0

    MFR = money_flow_ratio = pmf / nmf
    MFI = money_flow_index = 100 * pmf / (pmf + nmf)

Args:
    high (pd.Series): Series of 'high's
    low (pd.Series): Series of 'low's
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    length (int): The sum period. Default: 14
    talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib
        version. Default: True
    drift (int): The difference period. Default: 1
"""
    offset (int): How many periods to offset the result. Default: 0

# 定义函数参数 offset,表示结果偏移的周期数,默认值为 0。
# 定义函数参数
Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)  # 填充缺失值的方法和值
    fill_method (value, optional): Type of fill method  # 填充方法的类型

# 返回一个新的 pandas Series 对象,表示生成的新特征
Returns:
    pd.Series: New feature generated.  # 返回新生成的特征,类型为 pandas 的 Series 对象

.\pandas-ta\pandas_ta\volume\nvi.py

# -*- coding: utf-8 -*-
# 从 pandas_ta 库中导入动量指标 roc
from pandas_ta.momentum import roc
# 从 pandas_ta 库中导入工具函数 get_offset, signed_series, verify_series
from pandas_ta.utils import get_offset, signed_series, verify_series


# 定义函数 nvi,计算负量指数(NVI)
def nvi(close, volume, length=None, initial=None, offset=None, **kwargs):
    """Indicator: Negative Volume Index (NVI)"""
    # 验证参数
   length = int(length) if length and length > 0 else 1
    initial = int(initial) if initial and initial > 0 else 1000
    close = verify_series(close, length)
    volume = verify_series(volume, length)
    offset = get_offset(offset)

    if close is None or volume is None: return

    # 计算结果
    roc_ = roc(close=close, length=length)
    signed_volume = signed_series(volume, 1)
    nvi = signed_volume[signed_volume < 0].abs() * roc_
    nvi.fillna(0, inplace=True)
    nvi.iloc[0] = initial
    nvi = nvi.cumsum()

    # 偏移
    if offset != 0:
        nvi = nvi.shift(offset)

    # 处理填充
    if "fillna" in kwargs:
        nvi.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        nvi.fillna(method=kwargs["fill_method"], inplace=True)

    # 命名和分类
    nvi.name = f"NVI_{length}"
    nvi.category = "volume"

    return nvi


# 设置 nvi 函数的文档字符串
nvi.__doc__ = \
"""Negative Volume Index (NVI)

The Negative Volume Index is a cumulative indicator that uses volume change in
an attempt to identify where smart money is active.

Sources:
    https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:negative_volume_inde
    https://www.motivewave.com/studies/negative_volume_index.htm

Calculation:
    Default Inputs:
        length=1, initial=1000
    ROC = Rate of Change

    roc = ROC(close, length)
    signed_volume = signed_series(volume, initial=1)
    nvi = signed_volume[signed_volume < 0].abs() * roc_
    nvi.fillna(0, inplace=True)
    nvi.iloc[0]= initial
    nvi = nvi.cumsum()

Args:
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    length (int): The short period. Default: 13
    initial (int): The short period. Default: 1000
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""

.\pandas-ta\pandas_ta\volume\obv.py

# -*- coding: utf-8 -*-
# 导入所需的库
from pandas_ta import Imports
from pandas_ta.utils import get_offset, signed_series, verify_series

# 定义 On Balance Volume (OBV) 指标函数
def obv(close, volume, talib=None, offset=None, **kwargs):
    """Indicator: On Balance Volume (OBV)"""
    # 验证参数
    # 确保 'close' 和 'volume' 是有效的 Series 对象
    close = verify_series(close)
    volume = verify_series(volume)
    # 获取偏移量
    offset = get_offset(offset)
    # 确定是否使用 TA Lib
    mode_tal = bool(talib) if isinstance(talib, bool) else True

    # 计算结果
    if Imports["talib"] and mode_tal:
        # 如果 TA Lib 可用且 talib 参数为 True,则使用 TA Lib 中的 OBV 函数
        from talib import OBV
        obv = OBV(close, volume)
    else:
        # 否则,计算 signed_volume 并累积求和得到 OBV
        signed_volume = signed_series(close, initial=1) * volume
        obv = signed_volume.cumsum()

    # 偏移结果
    if offset != 0:
        obv = obv.shift(offset)

    # 处理填充
    # 如果 'fillna' 参数存在,则使用指定值填充缺失值
    if "fillna" in kwargs:
        obv.fillna(kwargs["fillna"], inplace=True)
    # 如果 'fill_method' 参数存在,则使用指定的填充方法填充缺失值
    if "fill_method" in kwargs:
        obv.fillna(method=kwargs["fill_method"], inplace=True)

    # 为结果添加名称和分类信息
    obv.name = f"OBV"
    obv.category = "volume"

    return obv


# 设置函数文档字符串
obv.__doc__ = \
"""On Balance Volume (OBV)

On Balance Volume is a cumulative indicator to measure buying and selling
pressure.

Sources:
    https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
    https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
    https://www.motivewave.com/studies/on_balance_volume.htm

Calculation:
    signed_volume = signed_series(close, initial=1) * volume
    obv = signed_volume.cumsum()

Args:
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib
        version. Default: True
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""

.\pandas-ta\pandas_ta\volume\pvi.py

# -*- coding: utf-8 -*-
# 从 pandas_ta 库中导入动量模块中的 roc 函数
from pandas_ta.momentum import roc
# 从 pandas_ta 库中导入工具模块中的 get_offset, signed_series, verify_series 函数
from pandas_ta.utils import get_offset, signed_series, verify_series


# 定义 Positive Volume Index (PVI) 指标函数
def pvi(close, volume, length=None, initial=None, offset=None, **kwargs):
    """Indicator: Positive Volume Index (PVI)"""
    # 验证参数
    length = int(length) if length and length > 0 else 1
    # initial 默认为 1000
    initial = int(initial) if initial and initial > 0 else 1000
    # 验证 close 和 volume 参数是否为 Series 类型,并且长度符合要求
    close = verify_series(close, length)
    volume = verify_series(volume, length)
    # 获取偏移量
    offset = get_offset(offset)

    # 如果 close 或 volume 为 None,则返回空
    if close is None or volume is None: return

    # 计算结果
    # 将 volume 序列转换为带符号的序列
    signed_volume = signed_series(volume, 1)
    # 计算 PVI
    pvi = roc(close=close, length=length) * signed_volume[signed_volume > 0].abs()
    # 将 NaN 值填充为 0
    pvi.fillna(0, inplace=True)
    # 将第一个值设置为 initial
    pvi.iloc[0] = initial
    # 对 PVI 序列进行累积求和
    pvi = pvi.cumsum()

    # 偏移
    if offset != 0:
        pvi = pvi.shift(offset)

    # 处理填充
    if "fillna" in kwargs:
        pvi.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        pvi.fillna(method=kwargs["fill_method"], inplace=True)

    # 设置指标名称和分类
    pvi.name = f"PVI_{length}"
    pvi.category = "volume"

    return pvi


# 设置 PVI 函数的文档字符串
pvi.__doc__ = \
"""Positive Volume Index (PVI)

The Positive Volume Index is a cumulative indicator that uses volume change in
an attempt to identify where smart money is active.
Used in conjunction with NVI.

Sources:
    https://www.investopedia.com/terms/p/pvi.asp

Calculation:
    Default Inputs:
        length=1, initial=1000
    ROC = Rate of Change

    roc = ROC(close, length)
    signed_volume = signed_series(volume, initial=1)
    pvi = signed_volume[signed_volume > 0].abs() * roc_
    pvi.fillna(0, inplace=True)
    pvi.iloc[0]= initial
    pvi = pvi.cumsum()

Args:
    close (pd.Series): Series of 'close's
    volume (pd.Series): Series of 'volume's
    length (int): The short period. Default: 13
    initial (int): The short period. Default: 1000
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""

标签:PandasTA,kwargs,volume,length,源码,offset,close,fillna,解析
From: https://www.cnblogs.com/apachecn/p/18135798

相关文章

  • PandasTA 源码解析(二十)
    .\pandas-ta\tests\test_indicator_cycles.py#从config模块中导入error_analysis,sample_data,CORRELATION,CORRELATION_THRESHOLD,VERBOSE变量#从context模块中导入pandas_tafrom.configimporterror_analysis,sample_data,CORRELATION,CORRELATION_THRESHOLD,VER......
  • PandasTA 源码解析(十九)
    .\pandas-ta\tests\test_ext_indicator_overlap_ext.py#从当前包中导入sample_data和pandas_ta模块from.configimportsample_datafrom.contextimportpandas_ta#从unittest模块中导入skip和TestCase类fromunittestimportskip,TestCase#从pandas模块......
  • PandasTA 源码解析(二十一)
    .\pandas-ta\tests\test_indicator_performance.py#导入所需的模块和函数from.configimportsample_datafrom.contextimportpandas_ta#从unittest模块中导入TestCase类fromunittestimportTestCase#从pandas模块中导入Series类frompandasimportSeries......
  • PandasTA 源码解析(一)
    .\pandas-ta\docs\conf.py#-*-coding:utf-8-*-##ConfigurationfilefortheSphinxdocumentationbuilder.##Thisfiledoesonlycontainaselectionofthemostcommonoptions.Fora#fulllistseethedocumentation:#http://www.sphinx-doc.org/e......
  • PandasTA 源码解析(二)
    .\pandas-ta\pandas_ta\candles\cdl_inside.py#-*-coding:utf-8-*-#从pandas_ta.utils中导入candle_color和get_offset函数frompandas_ta.utilsimportcandle_color,get_offset#从pandas_ta.utils中导入verify_series函数frompandas_ta.utilsimportve......
  • PandasTA 源码解析(四)
    .\pandas-ta\pandas_ta\momentum\cg.py#-*-coding:utf-8-*-#从pandas_ta.utils中导入get_offset,verify_series,weights函数frompandas_ta.utilsimportget_offset,verify_series,weights#定义CenterofGravity(CG)指标函数defcg(close,length=None,......
  • PandasTA 源码解析(三)
    .\pandas-ta\pandas_ta\custom.py#设置文件编码为UTF-8#-*-coding:utf-8-*-#导入必要的模块importimportlib#动态导入模块的工具importos#提供与操作系统交互的功能importsys#提供与Python解释器交互的功能importtypes#提供对Python类型和类的......
  • PandasTA 源码解析(六)
    .\pandas-ta\pandas_ta\momentum\rsi.py#-*-coding:utf-8-*-#导入所需模块和函数frompandasimportDataFrame,concatfrompandas_taimportImportsfrompandas_ta.overlapimportrmafrompandas_ta.utilsimportget_drift,get_offset,verify_series,signals......
  • PandasTA 源码解析(五)
    .\pandas-ta\pandas_ta\momentum\kst.py#-*-coding:utf-8-*-#导入DataFrame类frompandasimportDataFrame#导入roc函数from.rocimportroc#导入验证序列函数、获取漂移和偏移的函数frompandas_ta.utilsimportget_drift,get_offset,verify_series#定义......
  • PandasTA 源码解析(八)
    .\pandas-ta\pandas_ta\momentum\__init__.py#设置文件编码为UTF-8#导入ao指标from.aoimportao#导入apo指标from.apoimportapo#导入bias指标from.biasimportbias#导入bop指标from.bopimportbop#导入brar指标from.brarimportbrar#导......