赞
踩
.\pandas-ta\pandas_ta\custom.py
# 设置文件编码为 UTF-8 # -*- coding: utf-8 -*- # 导入必要的模块 import importlib # 动态导入模块的工具 import os # 提供与操作系统交互的功能 import sys # 提供与 Python 解释器交互的功能 import types # 提供对 Python 类型和类的支持 # 从 os.path 模块中导入指定函数,避免命名冲突 from os.path import abspath, join, exists, basename, splitext # 从 glob 模块中导入指定函数,用于文件匹配 from glob import glob # 导入 pandas_ta 模块,并指定 AnalysisIndicators 类 import pandas_ta from pandas_ta import AnalysisIndicators def bind(function_name, function, method): """ 辅助函数,将自定义指标模块中定义的函数和类方法绑定到活动的 pandas_ta 实例。 Args: function_name (str): 在 pandas_ta 中指标的名称 function (fcn): 指标函数 method (fcn): 与传递的函数对应的类方法 """ # 将指标函数绑定到 pandas_ta 实例 setattr(pandas_ta, function_name, function) # 将类方法绑定到 AnalysisIndicators 类 setattr(AnalysisIndicators, function_name, method) def create_dir(path, create_categories=True, verbose=True): """ 辅助函数,为使用自定义指标设置合适的文件夹结构。每当想要设置新的自定义指标文件夹时,只需调用此函数一次。 Args: path (str): 指标树的完整路径 create_categories (bool): 如果为 True,则创建类别子文件夹 verbose (bool): 如果为 True,则打印结果的详细输出 """ # 确保传递的目录存在/可读 if not exists(path): os.makedirs(path) # 如果 verbose 为 True,则打印已创建主目录的消息 if verbose: print(f"[i] Created main directory '{path}'.") # 列出目录的内容 # dirs = glob(abspath(join(path, '*'))) # 可选地添加任何缺少的类别子目录 if create_categories: for sd in [*pandas_ta.Category]: d = abspath(join(path, sd)) if not exists(d): os.makedirs(d) # 如果 verbose 为 True,则打印已创建空子目录的消息 if verbose: dirname = basename(d) print(f"[i] Created an empty sub-directory '{dirname}'.") def get_module_functions(module): """ 辅助函数,以字典形式获取导入模块的函数。 Args: module: Python 模块 Returns: dict: 模块函数映射 { "func1_name": func1, "func2_name": func2,... } """ module_functions = {} for name, item in vars(module).items(): if isinstance(item, types.FunctionType): module_functions[name] = item return module_functions def import_dir(path, verbose=True): # 确保传递的目录存在/可读 if not exists(path): print(f"[X] Unable to read the directory '{path}'.") return # 列出目录的内容 dirs = glob(abspath(join(path, "*"))) # 遍历整个目录,导入找到的所有模块 # 对每个目录进行遍历 for d in dirs: # 获取目录的基本名称 dirname = basename(d) # 仅在目录是有效的 pandas_ta 类别时才进行处理 if dirname not in [*pandas_ta.Category]: # 如果启用了详细输出,则打印消息跳过非有效 pandas_ta 类别的子目录 if verbose: print(f"[i] Skipping the sub-directory '{dirname}' since it's not a valid pandas_ta category.") continue # 对该类别(目录)中找到的每个模块进行处理 for module in glob(abspath(join(path, dirname, "*.py"))): # 获取模块的名称(不带扩展名) module_name = splitext(basename(module))[0] # 确保提供的路径被包含在我们的 Python 路径中 if d not in sys.path: sys.path.append(d) # (重新)加载指标模块 module_functions = load_indicator_module(module_name) # 确定要绑定到 pandas_ta 的哪些模块函数 fcn_callable = module_functions.get(module_name, None) fcn_method_callable = module_functions.get(f"{module_name}_method", None) # 如果找不到可调用的函数,则打印错误消息并继续下一个模块 if fcn_callable == None: print(f"[X] Unable to find a function named '{module_name}' in the module '{module_name}.py'.") continue # 如果找不到可调用的方法函数,则打印错误消息并继续下一个模块 if fcn_method_callable == None: missing_method = f"{module_name}_method" print(f"[X] Unable to find a method function named '{missing_method}' in the module '{module_name}.py'.") continue # 如果模块名称尚未在相应类别中,则将其添加到类别中 if module_name not in pandas_ta.Category[dirname]: pandas_ta.Category[dirname].append(module_name) # 将函数绑定到 pandas_ta bind(module_name, fcn_callable, fcn_method_callable) # 如果启用了详细输出,则打印成功导入自定义指标的消息 if verbose: print(f"[i] Successfully imported the custom indicator '{module}' into category '{dirname}'.") # 将 import_dir 函数的文档字符串赋值给 import_dir.__doc__,用于说明该函数的作用和用法 import_dir.__doc__ = \ """ Import a directory of custom indicators into pandas_ta Args: path (str): Full path to your indicator tree # 参数:指定自定义指标所在目录的完整路径 verbose (bool): If True verbose output of results # 参数:如果为 True,则输出详细的结果信息 This method allows you to experiment and develop your own technical analysis indicators in a separate local directory of your choice but use them seamlessly together with the existing pandas_ta functions just like if they were part of pandas_ta. If you at some late point would like to push them into the pandas_ta library you can do so very easily by following the step by step instruction here https://github.com/twopirllc/pandas-ta/issues/355. A brief example of usage: 1. Loading the 'ta' module: >>> import pandas as pd >>> import pandas_ta as ta 2. Create an empty directory on your machine where you want to work with your indicators. Invoke pandas_ta.custom.import_dir once to pre-populate it with sub-folders for all available indicator categories, e.g.: >>> import os >>> from os.path import abspath, join, expanduser >>> from pandas_ta.custom import create_dir, import_dir >>> ta_dir = abspath(join(expanduser("~"), "my_indicators")) >>> create_dir(ta_dir) 3. You can now create your own custom indicator e.g. by copying existing ones from pandas_ta core module and modifying them. IMPORTANT: Each custom indicator should have a unique name and have both a) a function named exactly as the module, e.g. 'ni' if the module is ni.py b) a matching method used by AnalysisIndicators named as the module but ending with '_method'. E.g. 'ni_method' In essence these modules should look exactly like the standard indicators available in categories under the pandas_ta-folder. The only difference will be an addition of a matching class method. For an example of the correct structure, look at the example ni.py in the examples folder. The ni.py indicator is a trend indicator so therefore we drop it into the sub-folder named trend. Thus we have a folder structure like this: ~/my_indicators/ │ ├── candles/ . . └── trend/ . └── ni.py . └── volume/ 4. We can now dynamically load all our custom indicators located in our designated indicators directory like this: >>> import_dir(ta_dir) If your custom indicator(s) loaded succesfully then it should behave exactly like all other native indicators in pandas_ta, including help functions. """ def load_indicator_module(name): """ Helper function to (re)load an indicator module. Returns: dict: module functions mapping { "func1_name": func1, "func2_name": func2,... } """ # 加载指标模块 try: module = importlib.import_module(name) except Exception as ex: # 捕获异常,如果加载模块出错则打印错误信息并退出程序 print(f"[X] An error occurred when attempting to load module {name}: {ex}") sys.exit(1) # 刷新之前加载的模块,以便重新加载 module = importlib.reload(module) # 返回模块函数的字典映射,包括模块中定义的所有函数 return get_module_functions(module)
# `.\pandas-ta\pandas_ta\cycles\ebsw.py` ```py # -*- coding: utf-8 -*- # 从 numpy 模块导入 cos 函数并命名为 npCos from numpy import cos as npCos # 从 numpy 模块导入 exp 函数并命名为 npExp from numpy import exp as npExp # 从 numpy 模块导入 nan 常量并命名为 npNaN from numpy import nan as npNaN # 从 numpy 模块导入 pi 常量并命名为 npPi from numpy import pi as npPi # 从 numpy 模块导入 sin 函数并命名为 npSin from numpy import sin as npSin # 从 numpy 模块导入 sqrt 函数并命名为 npSqrt from numpy import sqrt as npSqrt # 从 pandas 模块中导入 Series 类 from pandas import Series # 从 pandas_ta.utils 模块中导入 get_offset 和 verify_series 函数 from pandas_ta.utils import get_offset, verify_series # 定义函数 ebsw,用于计算 Even Better SineWave (EBSW) 指标 def ebsw(close, length=None, bars=None, offset=None, **kwargs): """Indicator: Even Better SineWave (EBSW)""" # 校验参数 # 如果 length 存在且大于38,则转换为整数,否则默认为40 length = int(length) if length and length > 38 else 40 # 如果 bars 存在且大于0,则转换为整数,否则默认为10 bars = int(bars) if bars and bars > 0 else 10 # 验证 close 是否为有效 Series 对象 close = verify_series(close, length) # 获取偏移量 offset = get_offset(offset) # 如果 close 为空,则返回 None if close is None: return # 初始化变量 alpha1 = HP = 0 # alpha 和 HighPass a1 = b1 = c1 = c2 = c3 = 0 Filt = Pwr = Wave = 0 lastClose = lastHP = 0 FilterHist = [0, 0] # 过滤器历史记录 # 计算结果 m = close.size result = [npNaN for _ in range(0, length - 1)] + [0] for i in range(length, m): # 使用周期为 length 的高通滤波器过滤短于 Duration 输入的周期成分 alpha1 = (1 - npSin(360 / length)) / npCos(360 / length) HP = 0.5 * (1 + alpha1) * (close[i] - lastClose) + alpha1 * lastHP # 使用超级平滑滤波器平滑数据(方程 3-3) a1 = npExp(-npSqrt(2) * npPi / bars) b1 = 2 * a1 * npCos(npSqrt(2) * 180 / bars) c2 = b1 c3 = -1 * a1 * a1 c1 = 1 - c2 - c3 Filt = c1 * (HP + lastHP) / 2 + c2 * FilterHist[1] + c3 * FilterHist[0] # 计算波动和功率的3根均线 Wave = (Filt + FilterHist[1] + FilterHist[0]) / 3 Pwr = (Filt * Filt + FilterHist[1] * FilterHist[1] + FilterHist[0] * FilterHist[0]) / 3 # 将平均波动归一化到平均功率的平方根 Wave = Wave / npSqrt(Pwr) # 更新存储和结果 FilterHist.append(Filt) # 添加新的 Filt 值 FilterHist.pop(0) # 移除列表中的第一个元素(最早的)-> 更新/修剪 lastHP = HP lastClose = close[i] result.append(Wave) # 创建结果 Series 对象 ebsw = Series(result, index=close.index) # 如果有偏移量,则进行偏移 if offset != 0: ebsw = ebsw.shift(offset) # 处理填充值 if "fillna" in kwargs: ebsw.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: ebsw.fillna(method=kwargs["fill_method"], inplace=True) # 设置指标名称和类别 ebsw.name = f"EBSW_{length}_{bars}" ebsw.category = "cycles" return ebsw # 设置函数 ebsw 的文档字符串 ebsw.__doc__ = \ """Even Better SineWave (EBSW) *beta* This indicator measures market cycles and uses a low pass filter to remove noise. Its output is bound signal between -1 and 1 and the maximum length of a detected trend is limited by its length input. Written by rengel8 for Pandas TA based on a publication at 'prorealcode.com' and a book by J.F.Ehlers. """ # 这个实现在逻辑上似乎有限制。最好实现与prorealcode中的版本完全相同,并比较行为。 来源: https://www.prorealcode.com/prorealtime-indicators/even-better-sinewave/ J.F.Ehlers的《Cycle Analytics for Traders》,2014 计算: 参考'sources'或实现 参数: close (pd.Series): 'close'的系列 length (int): 最大周期/趋势周期。值在40-48之间的效果如预期,最小值为39。默认值:40。 bars (int): 低通滤波的周期。默认值:10 drift (int): 差异周期。默认值:1 offset (int): 结果的偏移周期数。默认值:0 关键字参数: fillna (value, optional): pd.DataFrame.fillna(value) fill_method (value, optional): 填充方法的类型 返回: pd.Series: 生成的新特征。
.\pandas-ta\pandas_ta\cycles\__init__.py
# 设置文件编码格式为 UTF-8
# 从当前目录下的 ebsw 模块中导入 ebsw 函数
from .ebsw import ebsw
.\pandas-ta\pandas_ta\momentum\ao.py
# -*- coding: utf-8 -*- # 从pandas_ta.overlap模块导入简单移动平均函数sma from pandas_ta.overlap import sma # 从pandas_ta.utils模块导入get_offset和verify_series函数 from pandas_ta.utils import get_offset, verify_series def ao(high, low, fast=None, slow=None, offset=None, **kwargs): """Indicator: Awesome Oscillator (AO)""" # 验证参数 # 如果fast存在且大于0,则转换为整数,否则默认为5 fast = int(fast) if fast and fast > 0 else 5 # 如果slow存在且大于0,则转换为整数,否则默认为34 slow = int(slow) if slow and slow > 0 else 34 # 如果slow小于fast,则交换它们的值 if slow < fast: fast, slow = slow, fast # 计算_length为fast和slow中的最大值 _length = max(fast, slow) # 验证high和low的Series长度为_length high = verify_series(high, _length) low = verify_series(low, _length) # 获取offset的偏移量 offset = get_offset(offset) # 如果high或low为None,则返回空 if high is None or low is None: return # 计算结果 # 计算中间价,即(high + low) / 2 median_price = 0.5 * (high + low) # 计算fast期间的简单移动平均 fast_sma = sma(median_price, fast) # 计算slow期间的简单移动平均 slow_sma = sma(median_price, slow) # 计算AO指标,即fast期间的SMA减去slow期间的SMA ao = fast_sma - slow_sma # 偏移结果 if offset != 0: # 将结果向前偏移offset个周期 ao = ao.shift(offset) # 处理填充 # 如果kwargs中有"fillna"参数,则用指定值填充空值 if "fillna" in kwargs: ao.fillna(kwargs["fillna"], inplace=True) # 如果kwargs中有"fill_method"参数,则使用指定的填充方法 if "fill_method" in kwargs: ao.fillna(method=kwargs["fill_method"], inplace=True) # 命名和分类 # 设置AO指标的名称,格式为"AO_{fast}_{slow}" ao.name = f"AO_{fast}_{slow}" # 设置AO指标的类别为动量 ao.category = "momentum" # 返回AO指标 return ao # 更新函数文档字符串 ao.__doc__ = \ """Awesome Oscillator (AO) The Awesome Oscillator is an indicator used to measure a security's momentum. AO is generally used to affirm trends or to anticipate possible reversals. Sources: https://www.tradingview.com/wiki/Awesome_Oscillator_(AO) https://www.ifcm.co.uk/ntx-indicators/awesome-oscillator Calculation: Default Inputs: fast=5, slow=34 SMA = Simple Moving Average median = (high + low) / 2 AO = SMA(median, fast) - SMA(median, slow) Args: high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's fast (int): The short period. Default: 5 slow (int): The long period. Default: 34 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\momentum\apo.py
# 设置文件编码为 UTF-8 # 导入所需模块 from pandas_ta import Imports # 导入移动平均函数 from pandas_ta.overlap import ma # 导入辅助函数 from pandas_ta.utils import get_offset, tal_ma, verify_series def apo(close, fast=None, slow=None, mamode=None, talib=None, offset=None, **kwargs): """Indicator: Absolute Price Oscillator (APO)""" # 验证参数有效性,如果未指定则使用默认值 fast = int(fast) if fast and fast > 0 else 12 slow = int(slow) if slow and slow > 0 else 26 # 如果慢周期小于快周期,交换它们 if slow < fast: fast, slow = slow, fast # 验证并准备输入序列 close = verify_series(close, max(fast, slow)) # 确定移动平均的模式,默认为简单移动平均 mamode = mamode if isinstance(mamode, str) else "sma" # 获取偏移量 offset = get_offset(offset) # 确定是否使用 TA-Lib 库进行计算,默认为 True mode_tal = bool(talib) if isinstance(talib, bool) else True # 如果输入序列为空,则返回 None if close is None: return # 计算结果 if Imports["talib"] and mode_tal: # 如果 TA-Lib 可用且需要使用它,则调用 TA-Lib 库计算 APO from talib import APO # 使用 TA-Lib 计算 APO apo = APO(close, fast, slow, tal_ma(mamode)) else: # 否则使用自定义移动平均函数计算 APO # 计算快速和慢速移动平均线 fastma = ma(mamode, close, length=fast) slowma = ma(mamode, close, length=slow) # 计算 APO apo = fastma - slowma # 根据偏移量调整结果 if offset != 0: apo = apo.shift(offset) # 处理填充值 if "fillna" in kwargs: apo.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: apo.fillna(method=kwargs["fill_method"], inplace=True) # 设置指标名称和分类 apo.name = f"APO_{fast}_{slow}" apo.category = "momentum" # 返回计算结果 return apo # 设置 APO 函数的文档字符串 apo.__doc__ = \ """Absolute Price Oscillator (APO) The Absolute Price Oscillator is an indicator used to measure a security's momentum. It is simply the difference of two Exponential Moving Averages (EMA) of two different periods. Note: APO and MACD lines are equivalent. Sources: https://www.tradingtechnologies.com/xtrader-help/x-study/technical-indicator-definitions/absolute-price-oscillator-apo/ Calculation: Default Inputs: fast=12, slow=26 SMA = Simple Moving Average APO = SMA(close, fast) - SMA(close, slow) Args: close (pd.Series): Series of 'close's fast (int): The short period. Default: 12 slow (int): The long period. Default: 26 mamode (str): See ```help(ta.ma)```py. Default: 'sma' 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\momentum\bias.py
# -*- coding: utf-8 -*- # 导入 pandas_ta 库中的 ma 函数 from pandas_ta.overlap import ma # 导入 pandas_ta 库中的 get_offset 和 verify_series 函数 from pandas_ta.utils import get_offset, verify_series # 定义 Bias 指标函数,接受 close、length、mamode、offset 等参数 def bias(close, length=None, mamode=None, offset=None, **kwargs): """Indicator: Bias (BIAS)""" # 验证参数合法性 # 如果未指定 length 或 length 小于等于 0,则默认为 26 length = int(length) if length and length > 0 else 26 # 如果未指定 mamode 或 mamode 不是字符串,则默认为 "sma" mamode = mamode if isinstance(mamode, str) else "sma" # 验证 close 是否为 Series,并指定长度为 length close = verify_series(close, length) # 获取 offset offset = get_offset(offset) # 如果 close 为 None,则返回 None if close is None: return # 计算结果 # 计算移动平均线,参数为 mamode、close 和 length bma = ma(mamode, close, length=length, **kwargs) # 计算 Bias,即 (close / bma) - 1 bias = (close / bma) - 1 # 偏移 # 如果 offset 不为 0,则对 Bias 进行偏移 if offset != 0: bias = bias.shift(offset) # 处理填充 # 如果 kwargs 中包含 "fillna",则使用该值填充 NaN if "fillna" in kwargs: bias.fillna(kwargs["fillna"], inplace=True) # 如果 kwargs 中包含 "fill_method",则使用指定的填充方法 if "fill_method" in kwargs: bias.fillna(method=kwargs["fill_method"], inplace=True) # 设置指标名称和类别 # 指标名称为 "BIAS_移动平均线名称",类别为 "momentum" bias.name = f"BIAS_{bma.name}" bias.category = "momentum" # 返回 Bias return bias # 设置 Bias 函数的文档字符串 bias.__doc__ = \ """Bias (BIAS) Rate of change between the source and a moving average. Sources: Few internet resources on definitive definition. Request by Github user homily, issue #46 Calculation: Default Inputs: length=26, MA='sma' BIAS = (close - MA(close, length)) / MA(close, length) = (close / MA(close, length)) - 1 Args: close (pd.Series): Series of 'close's length (int): The period. Default: 26 mamode (str): See ```help(ta.ma)```py. Default: 'sma' drift (int): The short 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\momentum\bop.py
# -*- coding: utf-8 -*- # 从 pandas_ta 库中导入必要的模块 from pandas_ta import Imports # 从 pandas_ta.utils 模块中导入 get_offset, non_zero_range, verify_series 函数 from pandas_ta.utils import get_offset, non_zero_range, verify_series def bop(open_, high, low, close, scalar=None, talib=None, offset=None, **kwargs): """Indicator: Balance of Power (BOP)""" # 验证参数 open_ = verify_series(open_) high = verify_series(high) low = verify_series(low) close = verify_series(close) scalar = float(scalar) if scalar else 1 offset = get_offset(offset) mode_tal = bool(talib) if isinstance(talib, bool) else True # 计算结果 if Imports["talib"] and mode_tal: from talib import BOP bop = BOP(open_, high, low, close) else: high_low_range = non_zero_range(high, low) close_open_range = non_zero_range(close, open_) bop = scalar * close_open_range / high_low_range # 偏移 if offset != 0: bop = bop.shift(offset) # 处理填充 if "fillna" in kwargs: bop.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: bop.fillna(method=kwargs["fill_method"], inplace=True) # 命名和分类 bop.name = f"BOP" bop.category = "momentum" return bop # 设置函数文档字符串 bop.__doc__ = \ """Balance of Power (BOP) Balance of Power measure the market strength of buyers against sellers. Sources: http://www.worden.com/TeleChartHelp/Content/Indicators/Balance_of_Power.htm Calculation: BOP = scalar * (close - open) / (high - low) Args: open (pd.Series): Series of 'open's high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's scalar (float): How much to magnify. Default: 1 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\momentum\brar.py
# 设置文件编码为 UTF-8 # 导入 DataFrame 类 from pandas import DataFrame # 从 pandas_ta.utils 中导入函数 get_drift, get_offset, non_zero_range, verify_series from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series # 定义函数 brar,计算 BRAR 指标 def brar(open_, high, low, close, length=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: BRAR (BRAR)""" # 验证参数 # 如果 length 存在且大于 0,则将其转换为整数,否则默认为 26 length = int(length) if length and length > 0 else 26 # 如果 scalar 存在,则将其转换为浮点数,否则默认为 100 scalar = float(scalar) if scalar else 100 # 计算 high 与 open 的非零范围 high_open_range = non_zero_range(high, open_) # 计算 open 与 low 的非零范围 open_low_range = non_zero_range(open_, low) # 验证输入的数据列,并截取长度为 length open_ = verify_series(open_, length) high = verify_series(high, length) low = verify_series(low, length) close = verify_series(close, length) # 获取漂移值 drift = get_drift(drift) # 获取偏移值 offset = get_offset(offset) # 如果任何输入数据为空,则返回空 if open_ is None or high is None or low is None or close is None: return # 计算结果 # 计算 high_close_yesterday,即 high 与 close 的差值 hcy = non_zero_range(high, close.shift(drift)) # 计算 close_yesterday_low,即 close 与 low 的差值 cyl = non_zero_range(close.shift(drift), low) # 将负值替换为零 hcy[hcy < 0] = 0 cyl[cyl < 0] = 0 # 计算 AR 和 BR 指标 # AR = scalar * HO 的长度为 length 的滚动和 / OL 的长度为 length 的滚动和 ar = scalar * high_open_range.rolling(length).sum() ar /= open_low_range.rolling(length).sum() # BR = scalar * HCY 的长度为 length 的滚动和 / CYL 的长度为 length 的滚动和 br = scalar * hcy.rolling(length).sum() br /= cyl.rolling(length).sum() # 偏移 if offset != 0: ar = ar.shift(offset) br = ar.shift(offset) # 处理填充值 if "fillna" in kwargs: ar.fillna(kwargs["fillna"], inplace=True) br.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: ar.fillna(method=kwargs["fill_method"], inplace=True) br.fillna(method=kwargs["fill_method"], inplace=True) # 设置指标名称和类别 _props = f"_{length}" ar.name = f"AR{_props}" br.name = f"BR{_props}" ar.category = br.category = "momentum" # 准备返回的 DataFrame brardf = DataFrame({ar.name: ar, br.name: br}) brardf.name = f"BRAR{_props}" brardf.category = "momentum" return brardf # 设置 brar 函数的文档字符串 brar.__doc__ = \ """BRAR (BRAR) BR and AR Sources: No internet resources on definitive definition. Request by Github user homily, issue #46 Calculation: Default Inputs: length=26, scalar=100 SUM = Sum HO_Diff = high - open OL_Diff = open - low HCY = high - close[-1] CYL = close[-1] - low HCY[HCY < 0] = 0 CYL[CYL < 0] = 0 AR = scalar * SUM(HO, length) / SUM(OL, length) BR = scalar * SUM(HCY, length) / SUM(CYL, length) Args: open_ (pd.Series): Series of 'open's high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's length (int): The period. Default: 26 scalar (float): How much to magnify. Default: 100 drift (int): The difference 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.DataFrame: ar, br columns. """
.\pandas-ta\pandas_ta\momentum\cci.py
# -*- coding: utf-8 -*- # 导入必要的库 from pandas_ta import Imports from pandas_ta.overlap import hlc3, sma from pandas_ta.statistics.mad import mad from pandas_ta.utils import get_offset, verify_series # 定义计算 CCI 指标的函数 def cci(high, low, close, length=None, c=None, talib=None, offset=None, **kwargs): """Indicator: Commodity Channel Index (CCI)""" # 验证参数 length = int(length) if length and length > 0 else 14 c = float(c) if c and c > 0 else 0.015 high = verify_series(high, length) low = verify_series(low, length) close = verify_series(close, length) 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: return # 计算结果 if Imports["talib"] and mode_tal: from talib import CCI cci = CCI(high, low, close, length) else: typical_price = hlc3(high=high, low=low, close=close) mean_typical_price = sma(typical_price, length=length) mad_typical_price = mad(typical_price, length=length) cci = typical_price - mean_typical_price cci /= c * mad_typical_price # 偏移结果 if offset != 0: cci = cci.shift(offset) # 处理填充 if "fillna" in kwargs: cci.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: cci.fillna(method=kwargs["fill_method"], inplace=True) # 命名和分类 cci.name = f"CCI_{length}_{c}" cci.category = "momentum" return cci # 设置函数文档 cci.__doc__ = \ """Commodity Channel Index (CCI) Commodity Channel Index is a momentum oscillator used to primarily identify overbought and oversold levels relative to a mean. Sources: https://www.tradingview.com/wiki/Commodity_Channel_Index_(CCI) Calculation: Default Inputs: length=14, c=0.015 SMA = Simple Moving Average MAD = Mean Absolute Deviation tp = typical_price = hlc3 = (high + low + close) / 3 mean_tp = SMA(tp, length) mad_tp = MAD(tp, length) CCI = (tp - mean_tp) / (c * mad_tp) Args: high (pd.Series): Series of 'high's low (pd.Series): Series of 'low's close (pd.Series): Series of 'close's length (int): It's period. Default: 14 c (float): Scaling Constant. Default: 0.015 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\momentum\cfo.py
# -*- coding: utf-8 -*- # 从 pandas_ta 库中导入 overlap 模块中的 linreg 函数 from pandas_ta.overlap import linreg # 从 pandas_ta 库中导入 utils 模块中的 get_drift, get_offset, verify_series 函数 from pandas_ta.utils import get_drift, get_offset, verify_series # 定义 Chande Forcast Oscillator (CFO) 函数 def cfo(close, length=None, scalar=None, drift=None, offset=None, **kwargs): """Indicator: Chande Forcast Oscillator (CFO)""" # 验证参数 length = int(length) if length and length > 0 else 9 scalar = float(scalar) if scalar else 100 # 验证 close 参数,确保其为有效的 pd.Series 对象,并应用 length 长度验证 close = verify_series(close, length) # 获取 drift 参数的值 drift = get_drift(drift) # 获取 offset 参数的值 offset = get_offset(offset) # 如果 close 为 None,则返回 None if close is None: return # 计算 Series 的线性回归 cfo = scalar * (close - linreg(close, length=length, tsf=True)) cfo /= close # 偏移 if offset != 0: cfo = cfo.shift(offset) # 处理填充 if "fillna" in kwargs: cfo.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: cfo.fillna(method=kwargs["fill_method"], inplace=True) # 命名和分类 cfo.name = f"CFO_{length}" cfo.category = "momentum" return cfo # 设置 CFO 函数的文档字符串 cfo.__doc__ = \ """Chande Forcast Oscillator (CFO) The Forecast Oscillator calculates the percentage difference between the actual price and the Time Series Forecast (the endpoint of a linear regression line). Sources: https://www.fmlabs.com/reference/default.htm?url=ForecastOscillator.htm Calculation: Default Inputs: length=9, drift=1, scalar=100 LINREG = Linear Regression CFO = scalar * (close - LINERREG(length, tdf=True)) / close Args: close (pd.Series): Series of 'close's length (int): The period. Default: 9 scalar (float): How much to magnify. Default: 100 drift (int): The short 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. """
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。