.\pandas-ta\pandas_ta\volume\pvol.py
# -*- coding: utf-8 -*-
# 导入所需的库和函数
from pandas_ta.utils import get_offset, signed_series, verify_series
# 定义函数 pvol,计算价格和成交量的乘积
def pvol(close, volume, offset=None, **kwargs):
"""Indicator: Price-Volume (PVOL)"""
# 验证参数的有效性
close = verify_series(close) # 验证价格序列
volume = verify_series(volume) # 验证成交量序列
offset = get_offset(offset) # 获取偏移量
signed = kwargs.pop("signed", False) # 获取 signed 参数,默认为 False
# 计算结果
pvol = close * volume # 计算价格和成交量的乘积
if signed:
pvol *= signed_series(close, 1) # 如果 signed 为 True,则乘以 close 的符号系列
# 偏移
if offset != 0:
pvol = pvol.shift(offset) # 对结果进行偏移
# 处理填充
if "fillna" in kwargs:
pvol.fillna(kwargs["fillna"], inplace=True) # 使用指定值填充缺失值
if "fill_method" in kwargs:
pvol.fillna(method=kwargs["fill_method"], inplace=True) # 使用指定的填充方法填充缺失值
# 设置名称和分类
pvol.name = f"PVOL" # 设置结果的名称
pvol.category = "volume" # 设置结果的分类
return pvol # 返回计算结果
pvol.__doc__ = \
"""Price-Volume (PVOL)
Returns a series of the product of price and volume.
Calculation:
if signed:
pvol = signed_series(close, 1) * close * volume
else:
pvol = close * volume
Args:
close (pd.Series): Series of 'close's
volume (pd.Series): Series of 'volume's
signed (bool): Keeps the sign of the difference in 'close's. 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\pvr.py
# -*- coding: utf-8 -*-
# 从pandas_ta.utils模块中导入verify_series函数
from pandas_ta.utils import verify_series
# 从numpy中导入别名为npNaN的nan值
from numpy import nan as npNaN
# 从pandas模块中导入Series类
from pandas import Series
# 定义函数pvr,计算价格成交量等级指标
def pvr(close, volume):
""" Indicator: Price Volume Rank"""
# 验证参数
close = verify_series(close)
volume = verify_series(volume)
# 计算结果
# 计算收盘价的差分并填充NaN值为0
close_diff = close.diff().fillna(0)
# 计算成交量的差分并填充NaN值为0
volume_diff = volume.diff().fillna(0)
# 创建与close索引相同的Series对象,并填充NaN值为npNaN
pvr_ = Series(npNaN, index=close.index)
# 根据条件设置pvr_中的值
pvr_.loc[(close_diff >= 0) & (volume_diff >= 0)] = 1
pvr_.loc[(close_diff >= 0) & (volume_diff < 0)] = 2
pvr_.loc[(close_diff < 0) & (volume_diff >= 0)] = 3
pvr_.loc[(close_diff < 0) & (volume_diff < 0)] = 4
# 设置名称和分类
pvr_.name = f"PVR"
pvr_.category = "volume"
return pvr_
# 设置函数pvr的文档字符串
pvr.__doc__ = \
"""Price Volume Rank
The Price Volume Rank was developed by Anthony J. Macek and is described in his
article in the June, 1994 issue of Technical Analysis of Stocks & Commodities
Magazine. It was developed as a simple indicator that could be calculated even
without a computer. The basic interpretation is to buy when the PV Rank is below
2.5 and sell when it is above 2.5.
Sources:
https://www.fmlabs.com/reference/default.htm?url=PVrank.htm
Calculation:
return 1 if 'close change' >= 0 and 'volume change' >= 0
return 2 if 'close change' >= 0 and 'volume change' < 0
return 3 if 'close change' < 0 and 'volume change' >= 0
return 4 if 'close change' < 0 and 'volume change' < 0
Args:
close (pd.Series): Series of 'close's
volume (pd.Series): Series of 'volume's
Returns:
pd.Series: New feature generated.
"""
.\pandas-ta\pandas_ta\volume\pvt.py
# -*- coding: utf-8 -*-
# 从 pandas_ta.momentum 模块中导入 roc 函数
from pandas_ta.momentum import roc
# 从 pandas_ta.utils 模块中导入 get_drift、get_offset、verify_series 函数
from pandas_ta.utils import get_drift, get_offset, verify_series
# 定义函数 pvt,计算价格-成交量趋势指标(Price-Volume Trend,PVT)
def pvt(close, volume, drift=None, offset=None, **kwargs):
"""Indicator: Price-Volume Trend (PVT)"""
# 验证参数
close = verify_series(close) # 验证并确保 close 是有效的 Series 类型
volume = verify_series(volume) # 验证并确保 volume 是有效的 Series 类型
drift = get_drift(drift) # 获取漂移参数的值
offset = get_offset(offset) # 获取偏移参数的值
# 计算结果
# 计算 ROC(收盘价的变化率)并乘以成交量
pv = roc(close=close, length=drift) * volume
# 计算 PVT 的累积值
pvt = pv.cumsum()
# 调整偏移
if offset != 0:
pvt = pvt.shift(offset) # 将结果向前或向后偏移指定的周期数
# 处理填充值
if "fillna" in kwargs:
pvt.fillna(kwargs["fillna"], inplace=True) # 使用指定的值填充缺失值
if "fill_method" in kwargs:
pvt.fillna(method=kwargs["fill_method"], inplace=True) # 使用指定的填充方法填充缺失值
# 命名并分类化结果
pvt.name = f"PVT" # 设置结果 Series 的名称
pvt.category = "volume" # 设置结果 Series 的分类
return pvt # 返回 PVT 结果的 Series
# 设置函数 pvt 的文档字符串
pvt.__doc__ = \
"""Price-Volume Trend (PVT)
The Price-Volume Trend utilizes the Rate of Change with volume to
and it's cumulative values to determine money flow.
Sources:
https://www.tradingview.com/wiki/Price_Volume_Trend_(PVT)
Calculation:
Default Inputs:
drift=1
ROC = Rate of Change
pv = ROC(close, drift) * volume
PVT = pv.cumsum()
Args:
close (pd.Series): Series of 'close's
volume (pd.Series): Series of 'volume's
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\vp.py
# -*- coding: utf-8 -*-
# 从 numpy 库中导入 array_split 函数
from numpy import array_split
# 从 numpy 库中导入 mean 函数
from numpy import mean
# 从 pandas 库中导入 cut、concat、DataFrame 函数
from pandas import cut, concat, DataFrame
# 从 pandas_ta.utils 模块中导入 signed_series、verify_series 函数
from pandas_ta.utils import signed_series, verify_series
def vp(close, volume, width=None, **kwargs):
"""Indicator: Volume Profile (VP)"""
# 验证参数
# 如果宽度参数存在且大于 0,则将其转换为整数类型,否则设为默认值 10
width = int(width) if width and width > 0 else 10
# 验证 close 数据序列,确保长度为 width
close = verify_series(close, width)
# 验证 volume 数据序列,确保长度为 width
volume = verify_series(volume, width)
# 从 kwargs 中弹出 sort_close 参数,默认值为 False
sort_close = kwargs.pop("sort_close", False)
# 如果 close 或 volume 为空,则返回 None
if close is None or volume is None: return
# 设置
# 生成符号价格序列,即 close 的涨跌情况,用于后续计算正负成交量
signed_price = signed_series(close, 1)
# 正成交量为 volume 与符号价格序列大于 0 的乘积
pos_volume = volume * signed_price[signed_price > 0]
pos_volume.name = volume.name
# 负成交量为 volume 与符号价格序列小于 0 的乘积,乘以 -1
neg_volume = -volume * signed_price[signed_price < 0]
neg_volume.name = volume.name
# 合并 close、正成交量、负成交量 到一个 DataFrame 中
vp = concat([close, pos_volume, neg_volume], axis=1)
close_col = f"{vp.columns[0]}"
high_price_col = f"high_{close_col}"
low_price_col = f"low_{close_col}"
mean_price_col = f"mean_{close_col}"
volume_col = f"{vp.columns[1]}"
pos_volume_col = f"pos_{volume_col}"
neg_volume_col = f"neg_{volume_col}"
total_volume_col = f"total_{volume_col}"
vp.columns = [close_col, pos_volume_col, neg_volume_col]
# sort_close: 在将数据切分为范围之前,是否根据收盘价进行排序。默认值为 False
# 如果为 False,则根据日期索引或时间顺序排序,而不是根据价格
if sort_close:
# 将 mean_price_col 列设置为 close_col 列的值
vp[mean_price_col] = vp[close_col]
# 按照 close_col 列的值进行分组,并计算各范围内的平均价、正成交量、负成交量
vpdf = vp.groupby(cut(vp[close_col], width, include_lowest=True, precision=2)).agg({
mean_price_col: mean,
pos_volume_col: sum,
neg_volume_col: sum,
})
# 从索引中获取范围的最低价格和最高价格
vpdf[low_price_col] = [x.left for x in vpdf.index]
vpdf[high_price_col] = [x.right for x in vpdf.index]
# 重置索引并重新排列列的顺序
vpdf = vpdf.reset_index(drop=True)
vpdf = vpdf[[low_price_col, mean_price_col, high_price_col, pos_volume_col, neg_volume_col]]
else:
# 将 vp DataFrame 切分为若干子 DataFrame,每个子 DataFrame 包含近似相等数量的数据点
vp_ranges = array_split(vp, width)
# 遍历每个子 DataFrame,计算范围内的最低价、平均价、最高价、正成交量、负成交量,并生成生成器对象
result = ({
low_price_col: r[close_col].min(),
mean_price_col: r[close_col].mean(),
high_price_col: r[close_col].max(),
pos_volume_col: r[pos_volume_col].sum(),
neg_volume_col: r[neg_volume_col].sum(),
} for r in vp_ranges)
# 将生成器对象转换为 DataFrame
vpdf = DataFrame(result)
# 计算总成交量,并添加到 DataFrame 中
vpdf[total_volume_col] = vpdf[pos_volume_col] + vpdf[neg_volume_col]
# 处理填充值
# 如果 kwargs 中包含 fillna 参数,则使用该参数填充 NaN 值
if "fillna" in kwargs:
vpdf.fillna(kwargs["fillna"], inplace=True)
# 如果 kwargs 中包含 fill_method 参数,则使用该参数填充 NaN 值
if "fill_method" in kwargs:
vpdf.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分类
vpdf.name = f"VP_{width}"
vpdf.category = "volume"
# 返回结果 DataFrame
return vpdf
# 将函数文档字符串设为指定内容
vp.__doc__ = \
"""Volume Profile (VP)
Calculates the Volume Profile by slicing price into ranges.
Note: Value Area is not calculated.
Sources:
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:volume_by_price
https://www.tradingview.com/wiki/Volume_Profile
http://www.ranchodinero.com/volume-tpo-essentials/
"""
# 访问指定网址以获取相关信息,这是一个网页链接
https://www.tradingtechnologies.com/blog/2013/05/15/volume-at-price/
# 计算函数
Calculation:
# 默认输入参数:宽度为10
Default Inputs:
width=10
# 将 'close'、'pos_volume'、'neg_volume' 三个 Series 按列合并成一个 DataFrame
vp = pd.concat([close, pos_volume, neg_volume], axis=1)
# 如果需要按 'close' 排序
if sort_close:
# 将 'close' 列按照指定宽度切割成不同范围的区间
vp_ranges = cut(vp[close_col], width)
# 对于每个区间,计算以下统计量:左边界、平均 'close'、右边界、'pos_volume'、'neg_volume',结果为一个字典
result = ({range_left, mean_close, range_right, pos_volume, neg_volume} foreach range in vp_ranges
# 如果不需要按 'close' 排序
else:
# 将 DataFrame 按照指定宽度等分成不同的区间
vp_ranges = np.array_split(vp, width)
# 对于每个区间,计算以下统计量:最低 'close'、平均 'close'、最高 'close'、'pos_volume'、'neg_volume',结果为一个字典
result = ({low_close, mean_close, high_close, pos_volume, neg_volume} foreach range in vp_ranges
# 将结果字典转换成 DataFrame
vpdf = pd.DataFrame(result)
# 计算总交易量并添加到 DataFrame 中
vpdf['total_volume'] = vpdf['pos_volume'] + vpdf['neg_volume']
# 参数说明
Args:
# 'close' 的 Series 数据
close (pd.Series): Series of 'close's
# 'volume' 的 Series 数据
volume (pd.Series): Series of 'volume's
# 将价格分布到的区间数,默认为10
width (int): How many ranges to distrubute price into. Default: 10
# 可选参数说明
Kwargs:
# 对于缺失值的填充值,默认为 pd.DataFrame.fillna(value)
fillna (value, optional): pd.DataFrame.fillna(value)
# 填充方法的类型,默认为 None
fill_method (value, optional): Type of fill method
# 是否在切割成区间之前按 'close' 进行排序,默认为 False
sort_close (value, optional): Whether to sort by close before splitting
into ranges. Default: False
# 返回结果
Returns:
# 生成的新特征的 DataFrame
pd.DataFrame: New feature generated.
.\pandas-ta\pandas_ta\volume\__init__.py
# -*- coding: utf-8 -*-
# 从当前包中导入ad模块
from .ad import ad
# 从当前包中导入adosc模块
from .adosc import adosc
# 从当前包中导入aobv模块
from .aobv import aobv
# 从当前包中导入cmf模块
from .cmf import cmf
# 从当前包中导入efi模块
from .efi import efi
# 从当前包中导入eom模块
from .eom import eom
# 从当前包中导入kvo模块
from .kvo import kvo
# 从当前包中导入mfi模块
from .mfi import mfi
# 从当前包中导入nvi模块
from .nvi import nvi
# 从当前包中导入obv模块
from .obv import obv
# 从当前包中导入pvi模块
from .pvi import pvi
# 从当前包中导入pvol模块
from .pvol import pvol
# 从当前包中导入pvr模块
from .pvr import pvr
# 从当前包中导入pvt模块
from .pvt import pvt
# 从当前包中导入vp模块
from .vp import vp
.\pandas-ta\pandas_ta\__init__.py
# 定义模块名称
name = "pandas_ta"
"""
.. moduleauthor:: Kevin Johnson
"""
# 导入模块
from importlib.util import find_spec
from pathlib import Path
from pkg_resources import get_distribution, DistributionNotFound
# 获取已安装的模块分布对象
_dist = get_distribution("pandas_ta")
try:
# 获取模块所在路径
here = Path(_dist.location) / __file__
# 检查文件是否存在
if not here.exists():
# 如果未安装,但存在其他已安装版本
raise DistributionNotFound
except DistributionNotFound:
# 如果未找到分布对象,则提示安装该项目
__version__ = "Please install this project with setup.py"
# 获取模块版本号
version = __version__ = _dist.version
# 检查导入的模块是否存在
Imports = {
"alphaVantage-api": find_spec("alphaVantageAPI") is not None,
"matplotlib": find_spec("matplotlib") is not None,
"mplfinance": find_spec("mplfinance") is not None,
"numba": find_spec("numba") is not None,
"yaml": find_spec("yaml") is not None,
"scipy": find_spec("scipy") is not None,
"sklearn": find_spec("sklearn") is not None,
"statsmodels": find_spec("statsmodels") is not None,
"stochastic": find_spec("stochastic") is not None,
"talib": find_spec("talib") is not None,
"tqdm": find_spec("tqdm") is not None,
"vectorbt": find_spec("vectorbt") is not None,
"yfinance": find_spec("yfinance") is not None,
}
# 不是最理想的,也不是动态的,但它可以工作。
# 之后会找到一个动态的解决方案。
Category = {
# 蜡烛图
"candles": [
"cdl_pattern", "cdl_z", "ha"
],
# 周期
"cycles": ["ebsw"],
# 动量
"momentum": [
"ao", "apo", "bias", "bop", "brar", "cci", "cfo", "cg", "cmo",
"coppock", "cti", "er", "eri", "fisher", "inertia", "kdj", "kst", "macd",
"mom", "pgo", "ppo", "psl", "pvo", "qqe", "roc", "rsi", "rsx", "rvgi",
"slope", "smi", "squeeze", "squeeze_pro", "stc", "stoch", "stochrsi", "td_seq", "trix",
"tsi", "uo", "willr"
],
# 重叠
"overlap": [
"alma", "dema", "ema", "fwma", "hilo", "hl2", "hlc3", "hma", "ichimoku",
"jma", "kama", "linreg", "mcgd", "midpoint", "midprice", "ohlc4",
"pwma", "rma", "sinwma", "sma", "ssf", "supertrend", "swma", "t3",
"tema", "trima", "vidya", "vwap", "vwma", "wcp", "wma", "zlma"
],
# 性能
"performance": ["log_return", "percent_return"],
# 统计
"statistics": [
"entropy", "kurtosis", "mad", "median", "quantile", "skew", "stdev",
"tos_stdevall", "variance", "zscore"
],
# 趋势
"trend": [
"adx", "amat", "aroon", "chop", "cksp", "decay", "decreasing", "dpo",
"increasing", "long_run", "psar", "qstick", "short_run", "tsignals",
"ttm_trend", "vhf", "vortex", "xsignals"
],
# 波动性
"volatility": [
"aberration", "accbands", "atr", "bbands", "donchian", "hwc", "kc", "massi",
"natr", "pdist", "rvi", "thermo", "true_range", "ui"
],
# 交易量,"vp" 或 "Volume Profile" 是独特的
}
# "volume" 键对应的值是一个列表,包含了各种技术指标的名称
"volume": [
"ad", # AD 指标,积累/分配线
"adosc", # AD 指标,震荡指标
"aobv", # 指标,累积/派发线
"cmf", # CMF 指标,资金流量指标
"efi", # EFI 指标,振荡器
"eom", # EOM 指标,指标
"kvo", # Klinger Oscillator(克林格震荡器)指标
"mfi", # MFI 指标,资金流指标
"nvi", # NVI 指标,价值线
"obv", # OBV 指标,累积/分配线
"pvi", # PVI 指标,价值线
"pvol", # PVO 指标,价值线
"pvr", # PVR 指标,价值线
"pvt" # PVT 指标,价值线
],
# 字典,用于指定聚合函数的方式,对于开盘价、最高价、最低价、收盘价和成交量分别指定了不同的聚合方式
CANGLE_AGG = {
"open": "first", # 开盘价取第一个值
"high": "max", # 最高价取最大值
"low": "min", # 最低价取最小值
"close": "last", # 收盘价取最后一个值
"volume": "sum" # 成交量取总和
}
# 字典,用于记录各个交易所的时区偏移
EXCHANGE_TZ = {
"NZSX": 12, # 新西兰股票交易所,时区偏移为+12
"ASX": 11, # 澳大利亚证券交易所,时区偏移为+11
"TSE": 9, # 东京证券交易所,时区偏移为+9
"HKE": 8, # 香港证券交易所,时区偏移为+8
"SSE": 8, # 上海证券交易所,时区偏移为+8
"SGX": 8, # 新加坡证券交易所,时区偏移为+8
"NSE": 5.5, # 印度证券交易所,时区偏移为+5.5
"DIFX": 4, # 迪拜金融市场,时区偏移为+4
"RTS": 3, # 莫斯科证券交易所,时区偏移为+3
"JSE": 2, # 南非证券交易所,时区偏移为+2
"FWB": 1, # 法兰克福证券交易所,时区偏移为+1
"LSE": 1, # 伦敦证券交易所,时区偏移为+1
"BMF": -2, # 巴西商品与期货交易所,时区偏移为-2
"NYSE": -4, # 纽约证券交易所,时区偏移为-4
"TSX": -4 # 多伦多证券交易所,时区偏移为-4
}
# 字典,用于定义一些时间相关的常量
RATE = {
"DAYS_PER_MONTH": 21, # 每月交易日数
"MINUTES_PER_HOUR": 60, # 每小时分钟数
"MONTHS_PER_YEAR": 12, # 每年月份数
"QUARTERS_PER_YEAR": 4, # 每年季度数
"TRADING_DAYS_PER_YEAR": 252, # 每年交易日数,保持为偶数
"TRADING_HOURS_PER_DAY": 6.5, # 每日交易小时数
"WEEKS_PER_YEAR": 52, # 每年周数
"YEARLY": 1 # 年度
}
# 从 pandas_ta.core 模块导入所有内容
from pandas_ta.core import *
.\pandas-ta\setup.py
# -*- coding: utf-8 -*-
# 导入 setup 函数,用于设置 Python 包的元数据和安装信息
from distutils.core import setup
# 定义长描述信息
long_description = "An easy to use Python 3 Pandas Extension with 130+ Technical Analysis Indicators. Can be called from a Pandas DataFrame or standalone like TA-Lib. Correlation tested with TA-Lib."
# 设置函数调用,用于设置 Python 包的元数据和安装信息
setup(
# 包的名称
name="pandas_ta",
# 包含的子包列表
packages=[
"pandas_ta",
"pandas_ta.candles",
"pandas_ta.cycles",
"pandas_ta.momentum",
"pandas_ta.overlap",
"pandas_ta.performance",
"pandas_ta.statistics",
"pandas_ta.trend",
"pandas_ta.utils",
"pandas_ta.utils.data",
"pandas_ta.volatility",
"pandas_ta.volume"
],
# 版本号
version=".".join(("0", "3", "14b")),
# 简要描述
description=long_description,
# 长描述
long_description=long_description,
# 作者
author="Kevin Johnson",
# 作者邮箱
author_email="[email protected]",
# 项目 URL
url="https://github.com/twopirllc/pandas-ta",
# 维护者
maintainer="Kevin Johnson",
# 维护者邮箱
maintainer_email="[email protected]",
# 下载 URL
download_url="https://github.com/twopirllc/pandas-ta.git",
# 关键字列表
keywords=["technical analysis", "trading", "python3", "pandas"],
# 许可证
license="The MIT License (MIT)",
# 分类信息列表
classifiers=[
"Development Status :: 4 - Beta",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Operating System :: OS Independent",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Intended Audience :: Developers",
"Intended Audience :: Financial and Insurance Industry",
"Intended Audience :: Science/Research",
"Topic :: Office/Business :: Financial",
"Topic :: Office/Business :: Financial :: Investment",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Information Analysis",
],
# 包数据配置
package_data={
"data": ["data/*.csv"],
},
# 安装依赖项
install_requires=["pandas"],
# 列出额外的依赖组(例如开发依赖)
extras_require={
"dev": [
"alphaVantage-api", "matplotlib", "mplfinance", "scipy",
"sklearn", "statsmodels", "stochastic",
"talib", "tqdm", "vectorbt", "yfinance",
],
"test": ["ta-lib"],
},
)
.\pandas-ta\tests\config.py
# 导入 os 模块,用于操作系统相关功能
import os
# 导入 pandas 模块中的 DatetimeIndex 和 read_csv 函数
from pandas import DatetimeIndex, read_csv
# 设定是否显示详细信息的标志
VERBOSE = True
# 设定警报和信息提示的图标
ALERT = f"[!]"
INFO = f"[i]"
# 设定相关性分析方法,这里选择使用 'corr',也可以选择 'sem'
CORRELATION = "corr" # "sem"
# 设定相关性阈值,小于 0.99 视为不理想
CORRELATION_THRESHOLD = 0.99 # Less than 0.99 is undesirable
# 读取样本数据集,使用 pandas 的 read_csv 函数
sample_data = read_csv(
f"data/SPY_D.csv", # 文件路径
index_col=0, # 以第一列作为索引
parse_dates=True, # 解析日期
infer_datetime_format=True, # 推断日期格式
keep_date_col=True, # 保留日期列
)
# 将日期列设置为索引,并丢弃原始日期列
sample_data.set_index(DatetimeIndex(sample_data["date"]), inplace=True, drop=True)
sample_data.drop("date", axis=1, inplace=True)
# 定义错误分析函数,用于输出错误信息
def error_analysis(df, kind, msg, icon=INFO, newline=True):
if VERBOSE: # 如果 VERBOSE 为 True,则输出信息
s = f"{icon} {df.name}['{kind}']: {msg}" # 构造输出字符串
if newline: # 如果需要换行
s = f"\n{s}" # 在字符串前添加换行符
print(s) # 打印信息
# `.\pandas-ta\tests\context.py`
```py
# 导入 os 模块,提供对操作系统功能的访问
import os
# 导入 sys 模块,提供对 Python 解释器的访问和控制
import sys
# 将当前文件所在目录的父目录添加到 Python 模块搜索路径中,以便导入自定义模块
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
# 导入 pandas_ta 模块,该模块提供了一系列用于技术分析的函数和指标
import pandas_ta
.\pandas-ta\tests\test_ext_indicator_candle.py
# 从config模块中导入sample_data
from .config import sample_data
# 从context模块中导入pandas_ta
from .context import pandas_ta
# 从unittest模块中导入TestCase和skip
from unittest import TestCase, skip
# 从pandas模块中导入DataFrame
from pandas import DataFrame
# 定义测试类TestCandleExtension,继承自TestCase类
class TestCandleExtension(TestCase):
# 设置类方法setUpClass,在所有测试用例执行前执行一次
@classmethod
def setUpClass(cls):
cls.data = sample_data
# 设置类方法tearDownClass,在所有测试用例执行后执行一次
@classmethod
def tearDownClass(cls):
del cls.data
# 定义实例方法setUp,在每个测试用例执行前执行一次
def setUp(self): pass
# 定义实例方法tearDown,在每个测试用例执行后执行一次
def tearDown(self): pass
# 测试CDL_DOJI_10_0.1模式的扩展
def test_cdl_doji_ext(self):
self.data.ta.cdl_pattern("doji", append=True)
# 断言self.data是DataFrame类型
self.assertIsInstance(self.data, DataFrame)
# 断言self.data的最后一列的列名为"CDL_DOJI_10_0.1"
self.assertEqual(self.data.columns[-1], "CDL_DOJI_10_0.1")
# 测试CDL_INSIDE模式的扩展
def test_cdl_inside_ext(self):
self.data.ta.cdl_pattern("inside", append=True)
# 断言self.data是DataFrame类型
self.assertIsInstance(self.data, DataFrame)
# 断言self.data的最后一列的列名为"CDL_INSIDE"
self.assertEqual(self.data.columns[-1], "CDL_INSIDE")
# 测试CDL_Z指标的扩展
def test_cdl_z_ext(self):
self.data.ta.cdl_z(append=True)
# 断言self.data是DataFrame类型
self.assertIsInstance(self.data, DataFrame)
# 断言self.data的倒数第四列到最后一列的列名为["open_Z_30_1", "high_Z_30_1", "low_Z_30_1", "close_Z_30_1"]
self.assertEqual(list(self.data.columns[-4:]), ["open_Z_30_1", "high_Z_30_1", "low_Z_30_1", "close_Z_30_1"])
# 测试HA指标的扩展
def test_ha_ext(self):
self.data.ta.ha(append=True)
# 断言self.data是DataFrame类型
self.assertIsInstance(self.data, DataFrame)
# 断言self.data的倒数第四列到最后一列的列名为["HA_open", "HA_high", "HA_low", "HA_close"]
self.assertEqual(list(self.data.columns[-4:]), ["HA_open", "HA_high", "HA_low", "HA_close"])
.\pandas-ta\tests\test_ext_indicator_cycles.py
# 从 pandas 库的 core.series 模块中导入 Series 类
from pandas.core.series import Series
# 从当前目录中的 config 模块中导入 sample_data 变量
from .config import sample_data
# 从当前目录中的 context 模块中导入 pandas_ta 模块
from .context import pandas_ta
# 从 unittest 模块中导入 TestCase 类
from unittest import TestCase
# 从 pandas 库中导入 DataFrame 类
from pandas import DataFrame
# 定义测试类 TestCylesExtension,继承自 TestCase 类
class TestCylesExtension(TestCase):
# 在整个测试类运行之前执行的方法,设置测试数据
@classmethod
def setUpClass(cls):
cls.data = sample_data
# 在整个测试类运行之后执行的方法,清理测试数据
@classmethod
def tearDownClass(cls):
del cls.data
# 在每个测试方法运行之前执行的方法
def setUp(self): pass
# 在每个测试方法运行之后执行的方法
def tearDown(self): pass
# 定义测试方法 test_ebsw_ext,测试 EBSW 扩展函数
def test_ebsw_ext(self):
# 调用数据框对象的 ta 属性中的 ebsw 方法,并将结果追加到原数据框中
self.data.ta.ebsw(append=True)
# 断言数据框对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言数据框对象的最后一列的列名为 "EBSW_40_10"
self.assertEqual(self.data.columns[-1], "EBSW_40_10")
.\pandas-ta\tests\test_ext_indicator_momentum.py
# 从config模块中导入sample_data变量
from .config import sample_data
# 从context模块中导入pandas_ta模块
from .context import pandas_ta
# 从unittest模块中导入skip和TestCase类
from unittest import skip, TestCase
# 从pandas模块中导入DataFrame类
from pandas import DataFrame
# 定义测试类TestMomentumExtension,继承自TestCase类
class TestMomentumExtension(TestCase):
# 类方法setUpClass,用于设置测试类的初始状态
@classmethod
def setUpClass(cls):
# 初始化数据,使用sample_data
cls.data = sample_data
# 类方法tearDownClass,用于清理测试类的状态
@classmethod
def tearDownClass(cls):
# 删除数据
del cls.data
# 实例方法setUp,用于设置每个测试方法的初始状态
def setUp(self): pass
# 实例方法tearDown,用于清理每个测试方法的状态
def tearDown(self): pass
# 测试AO扩展函数
def test_ao_ext(self):
# 在数据上计算AO指标,并将结果追加到数据中
self.data.ta.ao(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"AO_5_34"
self.assertEqual(self.data.columns[-1], "AO_5_34")
# 测试APO扩展函数
def test_apo_ext(self):
# 在数据上计算APO指标,并将结果追加到数据中
self.data.ta.apo(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"APO_12_26"
self.assertEqual(self.data.columns[-1], "APO_12_26")
# 测试BIAS扩展函数
def test_bias_ext(self):
# 在数据上计算BIAS指标,并将结果追加到数据中
self.data.ta.bias(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"BIAS_SMA_26"
self.assertEqual(self.data.columns[-1], "BIAS_SMA_26")
# 测试BOP扩展函数
def test_bop_ext(self):
# 在数据上计算BOP指标,并将结果追加到数据中
self.data.ta.bop(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"BOP"
self.assertEqual(self.data.columns[-1], "BOP")
# 测试BRAR扩展函数
def test_brar_ext(self):
# 在数据上计算BRAR指标,并将结果追加到数据中
self.data.ta.brar(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言倒数第二列和最后一列的列名分别为"AR_26"和"BR_26"
self.assertEqual(list(self.data.columns[-2:]), ["AR_26", "BR_26"])
# 测试CCI扩展函数
def test_cci_ext(self):
# 在数据上计算CCI指标,并将结果追加到数据中
self.data.ta.cci(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"CCI_14_0.015"
self.assertEqual(self.data.columns[-1], "CCI_14_0.015")
# 测试CFO扩展函数
def test_cfo_ext(self):
# 在数据上计算CFO指标,并将结果追加到数据中
self.data.ta.cfo(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"CFO_9"
self.assertEqual(self.data.columns[-1], "CFO_9")
# 测试CG扩展函数
def test_cg_ext(self):
# 在数据上计算CG指标,并将结果追加到数据中
self.data.ta.cg(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"CG_10"
self.assertEqual(self.data.columns[-1], "CG_10")
# 测试CMO扩展函数
def test_cmo_ext(self):
# 在数据上计算CMO指标,并将结果追加到数据中
self.data.ta.cmo(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"CMO_14"
self.assertEqual(self.data.columns[-1], "CMO_14")
# 测试Coppock指标扩展函数
def test_coppock_ext(self):
# 在数据上计算Coppock指标,并将结果追加到数据中
self.data.ta.coppock(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"COPC_11_14_10"
self.assertEqual(self.data.columns[-1], "COPC_11_14_10")
# 测试CTI扩展函数
def test_cti_ext(self):
# 在数据上计算CTI指标,并将结果追加到数据中
self.data.ta.cti(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"CTI_12"
self.assertEqual(self.data.columns[-1], "CTI_12")
# 测试ER扩展函数
def test_er_ext(self):
# 在数据上计算ER指标,并将结果追加到数据中
self.data.ta.er(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"ER_10"
self.assertEqual(self.data.columns[-1], "ER_10")
# 测试ERI扩展函数
def test_eri_ext(self):
# 在数据上计算ERI指标,并将结果追加到数据中
self
# 测试计算惯性指标,并将结果追加到数据框中
def test_inertia_ext(self):
# 调用惯性指标计算函数,将结果追加到数据框中
self.data.ta.inertia(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"INERTIA_20_14"
self.assertEqual(self.data.columns[-1], "INERTIA_20_14")
# 测试计算经过优化的惯性指标,并将结果追加到数据框中
def test_inertia_refined_ext(self):
# 调用经过优化的惯性指标计算函数,将结果追加到数据框中
self.data.ta.inertia(refined=True, append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"INERTIAr_20_14"
self.assertEqual(self.data.columns[-1], "INERTIAr_20_14")
# 测试计算经过划分的惯性指标,并将结果追加到数据框中
def test_inertia_thirds_ext(self):
# 调用经过划分的惯性指标计算函数,将结果追加到数据框中
self.data.ta.inertia(thirds=True, append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"INERTIAt_20_14"
self.assertEqual(self.data.columns[-1], "INERTIAt_20_14")
# 测试计算KDJ指标,并将结果追加到数据框中
def test_kdj_ext(self):
# 调用KDJ指标计算函数,将结果追加到数据框中
self.data.ta.kdj(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后三列的列名分别为"K_9_3", "D_9_3", "J_9_3"
self.assertEqual(list(self.data.columns[-3:]), ["K_9_3", "D_9_3", "J_9_3"])
# 测试计算KST指标,并将结果追加到数据框中
def test_kst_ext(self):
# 调用KST指标计算函数,将结果追加到数据框中
self.data.ta.kst(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后两列的列名分别为"KST_10_15_20_30_10_10_10_15", "KSTs_9"
self.assertEqual(list(self.data.columns[-2:]), ["KST_10_15_20_30_10_10_10_15", "KSTs_9"])
# 测试计算MACD指标,并将结果追加到数据框中
def test_macd_ext(self):
# 调用MACD指标计算函数,将结果追加到数据框中
self.data.ta.macd(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后三列的列名分别为"MACD_12_26_9", "MACDh_12_26_9", "MACDs_12_26_9"
self.assertEqual(list(self.data.columns[-3:]), ["MACD_12_26_9", "MACDh_12_26_9", "MACDs_12_26_9"])
# 测试计算动量指标,并将结果追加到数据框中
def test_mom_ext(self):
# 调用动量指标计算函数,将结果追加到数据框中
self.data.ta.mom(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"MOM_10"
self.assertEqual(self.data.columns[-1], "MOM_10")
# 测试计算价格振荡指标,并将结果追加到数据框中
def test_pgo_ext(self):
# 调用价格振荡指标计算函数,将结果追加到数据框中
self.data.ta.pgo(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"PGO_14"
self.assertEqual(self.data.columns[-1], "PGO_14")
# 测试计算价格百分比振荡指标,并将结果追加到数据框中
def test_ppo_ext(self):
# 调用价格百分比振荡指标计算函数,将结果追加到数据框中
self.data.ta.ppo(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后三列的列名分别为"PPO_12_26_9", "PPOh_12_26_9", "PPOs_12_26_9"
self.assertEqual(list(self.data.columns[-3:]), ["PPO_12_26_9", "PPOh_12_26_9", "PPOs_12_26_9"])
# 测试计算平滑移动线指标,并将结果追加到数据框中
def test_psl_ext(self):
# 调用平滑移动线指标计算函数,将结果追加到数据框中
self.data.ta.psl(append=True)
# 断言数据类型为DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为"PSL_12"
self.assertEqual(self.data.columns[-1], "PSL_12")
# 测试计算成交量价格振荡指标,并将结果追加到数据框中
def test_pvo_ext(self):
# 调用成交量价格振荡指标计算函数,将结果追加到数据框中
self.data.ta.pvo(append=True)
# 断言数据类型为
# 测试 RSX 指标是否正确计算并追加到数据中
def test_rsx_ext(self):
# 计算 RSX 指标并追加到数据中
self.data.ta.rsx(append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为 "RSX_14"
self.assertEqual(self.data.columns[-1], "RSX_14")
# 测试 RVGI 指标是否正确计算并追加到数据中
def test_rvgi_ext(self):
# 计算 RVGI 指标并追加到数据中
self.data.ta.rvgi(append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后两列的列名为 "RVGI_14_4" 和 "RVGIs_14_4"
self.assertEqual(list(self.data.columns[-2:]), ["RVGI_14_4", "RVGIs_14_4"])
# 测试斜率指标是否正确计算并追加到数据中
def test_slope_ext(self):
# 计算斜率指标并追加到数据中
self.data.ta.slope(append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为 "SLOPE_1"
self.assertEqual(self.data.columns[-1], "SLOPE_1")
# 计算角度形式的斜率指标并追加到数据中
self.data.ta.slope(append=True, as_angle=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为 "ANGLEr_1"
self.assertEqual(self.data.columns[-1], "ANGLEr_1")
# 计算以角度形式表示的斜率指标并追加到数据中
self.data.ta.slope(append=True, as_angle=True, to_degrees=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为 "ANGLEd_1"
self.assertEqual(self.data.columns[-1], "ANGLEd_1")
# 测试 SMI 指标是否正确计算并追加到数据中
def test_smi_ext(self):
# 计算 SMI 指标并追加到数据中
self.data.ta.smi(append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后三列的列名为 "SMI_5_20_5", "SMIs_5_20_5", "SMIo_5_20_5"
self.assertEqual(list(self.data.columns[-3:]), ["SMI_5_20_5", "SMIs_5_20_5", "SMIo_5_20_5"])
# 计算带有自定义标量的 SMI 指标并追加到数据中
self.data.ta.smi(scalar=10, append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后三列的列名为 "SMI_5_20_5_10.0", "SMIs_5_20_5_10.0", "SMIo_5_20_5_10.0"
self.assertEqual(list(self.data.columns[-3:]), ["SMI_5_20_5_10.0", "SMIs_5_20_5_10.0", "SMIo_5_20_5_10.0"])
# 测试挤牌指标是否正确计算并追加到数据中
def test_squeeze_ext(self):
# 计算挤牌指标并追加到数据中
self.data.ta.squeeze(append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后四列的列名为 "SQZ_20_2.0_20_1.5", "SQZ_ON", "SQZ_OFF", "SQZ_NO"
self.assertEqual(list(self.data.columns[-4:]), ["SQZ_20_2.0_20_1.5", "SQZ_ON", "SQZ_OFF", "SQZ_NO"])
# 计算不带有挤牌 true range 的挤牌指标并追加到数据中
self.data.ta.squeeze(tr=False, append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后四列的列名为 "SQZ_ON", "SQZ_OFF", "SQZ_NO", "SQZhlr_20_2.0_20_1.5"
self.assertEqual(list(self.data.columns[-4:]),
["SQZ_ON", "SQZ_OFF", "SQZ_NO", "SQZhlr_20_2.0_20_1.5"]
)
# 测试高级挤牌指标是否正确计算并追加到数据中
def test_squeeze_pro_ext(self):
# 计算高级挤牌指标并追加到数据中
self.data.ta.squeeze_pro(append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后四列的列名为 "SQZPRO_ON_NORMAL", "SQZPRO_ON_NARROW", "SQZPRO_OFF", "SQZPRO_NO"
self.assertEqual(list(self.data.columns[-4:]), ["SQZPRO_ON_NORMAL", "SQZPRO_ON_NARROW", "SQZPRO_OFF", "SQZPRO_NO"])
# 计算不带有挤牌 true range 的高级挤牌指标并追加到数据中
self.data.ta.squeeze_pro(tr=False, append=True)
# 断言数据类型为 DataFrame
self.assertIsInstance(self.data, DataFrame)
# 断言最后四列的列名为 "SQZPRO_ON_NARROW", "SQZPRO_OFF", "SQZPRO_NO", "SQZPROhlr_20_2.0_20_2_1.5_1"
self.assertEqual(
list(self.data.columns[-4:]),
["SQZPRO_ON_NARROW", "SQZPRO_OFF", "SQZPRO_NO", "SQZPROhlr_20_2.0_20_2_1.5_1"]
)
# 测试 ST
# 测试 Stochastic RSI 扩展功能
def test_stochrsi_ext(self):
# 计算 Stochastic RSI,并将结果追加到数据框中
self.data.ta.stochrsi(append=True)
# 断言数据对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言最后两列的列名为指定值
self.assertEqual(list(self.data.columns[-2:]), ["STOCHRSIk_14_14_3_3", "STOCHRSId_14_14_3_3"])
# 跳过该测试
@skip
def test_td_seq_ext(self):
"""TS Sequential DataFrame: Working but SLOW implementation"""
# 计算 TD Sequential,并将结果追加到数据框中
self.data.ta.td_seq(show_all=False, append=True)
# 断言数据对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言最后两列的列名为指定值
self.assertEqual(list(self.data.columns[-2:]), ["TD_SEQ_UP", "TD_SEQ_DN"])
# 计算 TD Sequential,并将结果追加到数据框中
self.data.ta.td_seq(show_all=True, append=True)
# 断言数据对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言最后两列的列名为指定值
self.assertEqual(list(self.data.columns[-2:]), ["TD_SEQ_UPa", "TD_SEQ_DNa"])
# 测试 TRIX 扩展功能
def test_trix_ext(self):
# 计算 TRIX,并将结果追加到数据框中
self.data.ta.trix(append=True)
# 断言数据对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言最后两列的列名为指定值
self.assertEqual(list(self.data.columns[-2:]), ["TRIX_30_9", "TRIXs_30_9"])
# 测试 TSI 扩展功能
def test_tsi_ext(self):
# 计算 TSI,并将结果追加到数据框中
self.data.ta.tsi(append=True)
# 断言数据对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言最后两列的列名为指定值
self.assertEqual(list(self.data.columns[-2:]), ["TSI_13_25_13", "TSIs_13_25_13"])
# 测试 Ultimate Oscillator 扩展功能
def test_uo_ext(self):
# 计算 Ultimate Oscillator,并将结果追加到数据框中
self.data.ta.uo(append=True)
# 断言数据对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为指定值
self.assertEqual(self.data.columns[-1], "UO_7_14_28")
# 测试 Williams %R 扩展功能
def test_willr_ext(self):
# 计算 Williams %R,并将结果追加到数据框中
self.data.ta.willr(append=True)
# 断言数据对象是 DataFrame 类型
self.assertIsInstance(self.data, DataFrame)
# 断言最后一列的列名为指定值
self.assertEqual(self.data.columns[-1], "WILLR_14")
标签:PandasTA,self,DataFrame,volume,源码,close,解析,data,ta
From: https://www.cnblogs.com/apachecn/p/18135799