.\pandas-ta\pandas_ta\statistics\stdev.py
# -*- coding: utf-8 -*-
# 從 numpy 匯入 sqrt 函式,並將其命名為 npsqrt
from numpy import sqrt as npsqrt
# 從 variance 模組匯入 variance 函式
from .variance import variance
# 從 pandas_ta 模組匯入 Imports 類
from pandas_ta import Imports
# 從 pandas_ta.utils 模組匯入 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 定義 stdev 函式,用於計算標準差
def stdev(close, length=None, ddof=None, talib=None, offset=None, **kwargs):
"""Indicator: Standard Deviation"""
# 驗證引數
# 如果 length 存在且大於 0,則將其轉換為整數,否則設為 30
length = int(length) if length and length > 0 else 30
# 如果 ddof 是整數且大於等於 0 且小於 length,則將其轉換為整數,否則設為 1
ddof = int(ddof) if isinstance(ddof, int) and ddof >= 0 and ddof < length else 1
# 驗證 close 引數是否為有效的 Series,並根據 length 進行截斷
close = verify_series(close, length)
# 獲取 offset 引數
offset = get_offset(offset)
# 如果 talib 存在且為布林值,則使用 talib 引數值,否則預設為 True
mode_tal = bool(talib) if isinstance(talib, bool) else True
# 如果 close 為 None,則返回
if close is None: return
# 計算結果
# 如果 Imports 中有 "talib" 並且 mode_tal 為 True
if Imports["talib"] and mode_tal:
# 從 talib 中匯入 STDDEV 函式,並計算標準差
from talib import STDDEV
stdev = STDDEV(close, length)
else:
# 否則使用自定義的 variance 函式計算方差,然後對結果應用平方根
stdev = variance(close=close, length=length, ddof=ddof).apply(npsqrt)
# 偏移結果
if offset != 0:
stdev = stdev.shift(offset)
# 處理填充
if "fillna" in kwargs:
stdev.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
stdev.fillna(method=kwargs["fill_method"], inplace=True)
# 設定名稱和類別
stdev.name = f"STDEV_{length}"
stdev.category = "statistics"
# 返回結果
return stdev
# 設定 stdev 函式的文件字串
stdev.__doc__ = \
"""Rolling Standard Deviation
Sources:
Calculation:
Default Inputs:
length=30
VAR = Variance
STDEV = variance(close, length).apply(np.sqrt)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 30
ddof (int): Delta Degrees of Freedom.
The divisor used in calculations is N - ddof,
where N represents the number of elements. 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\statistics\tos_stdevall.py
# -*- coding: utf-8 -*-
# 從 numpy 庫中匯入 array 別名為 npArray
from numpy import array as npArray
# 從 numpy 庫中匯入 arange 別名為 npArange
from numpy import arange as npArange
# 從 numpy 庫中匯入 polyfit 別名為 npPolyfit
from numpy import polyfit as npPolyfit
# 從 numpy 庫中匯入 std 別名為 npStd
from numpy import std as npStd
# 從 pandas 庫中匯入 DataFrame、DatetimeIndex、Series
from pandas import DataFrame, DatetimeIndex, Series
# 從 .stdev 模組中匯入 stdev 別名為 stdev
from .stdev import stdev as stdev
# 從 pandas_ta.utils 模組中匯入 get_offset、verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 定義函式 tos_stdevall,計算 Think or Swim 標準偏差
def tos_stdevall(close, length=None, stds=None, ddof=None, offset=None, **kwargs):
"""Indicator: TD Ameritrade's Think or Swim Standard Deviation All"""
# 驗證引數
# 如果 stds 是非空列表,則使用 stds,否則預設為 [1, 2, 3]
stds = stds if isinstance(stds, list) and len(stds) > 0 else [1, 2, 3]
# 如果 stds 中有小於等於 0 的數,則返回空
if min(stds) <= 0: return
# 如果 stds 中存在逆序排列,則將其反轉為升序排列
if not all(i < j for i, j in zip(stds, stds[1:])):
stds = stds[::-1]
# 將 ddof 轉換為整數,確保在合理範圍內,預設為 1
ddof = int(ddof) if ddof and ddof >= 0 and ddof < length else 1
# 獲取偏移量
offset = get_offset(offset)
# 屬性名稱
_props = f"TOS_STDEVALL"
# 如果 length 為 None,則使用全部資料;否則,使用指定長度的資料
if length is None:
length = close.size
else:
# 將 length 轉換為整數,確保大於 2,預設為 30
length = int(length) if isinstance(length, int) and length > 2 else 30
# 僅保留最近 length 個資料
close = close.iloc[-length:]
_props = f"{_props}_{length}"
# 確保 close 是一個 Series,並且長度為 length
close = verify_series(close, length)
# 如果 close 為空,則返回空
if close is None: return
# 計算結果
X = src_index = close.index
# 如果 close 的索引是 DatetimeIndex 型別,則建立等差陣列 X,並將 close 轉換為陣列
if isinstance(close.index, DatetimeIndex):
X = npArange(length)
close = npArray(close)
# 使用線性迴歸擬合得到斜率 m 和截距 b
m, b = npPolyfit(X, close, 1)
# 計算線性迴歸線 lr,索引與 close 保持一致
lr = Series(m * X + b, index=src_index)
# 計算標準差 stdev
stdev = npStd(close, ddof=ddof)
# 組裝結果 DataFrame
df = DataFrame({f"{_props}_LR": lr}, index=src_index)
# 對於每個標準偏差值,計算上下界,並設定名稱和分類
for i in stds:
df[f"{_props}_L_{i}"] = lr - i * stdev
df[f"{_props}_U_{i}"] = lr + i * stdev
df[f"{_props}_L_{i}"].name = df[f"{_props}_U_{i}"].name = f"{_props}"
df[f"{_props}_L_{i}"].category = df[f"{_props}_U_{i}"].category = "statistics"
# 對結果進行偏移
if offset != 0:
df = df.shift(offset)
# 處理填充值
if "fillna" in kwargs:
df.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
df.fillna(method=kwargs["fill_method"], inplace=True)
# 準備返回的 DataFrame
df.name = f"{_props}"
df.category = "statistics"
return df
# 設定函式的文件字串
tos_stdevall.__doc__ = \
"""TD Ameritrade's Think or Swim Standard Deviation All (TOS_STDEV)
A port of TD Ameritrade's Think or Swim Standard Deviation All indicator which
returns the standard deviation of data for the entire plot or for the interval
of the last bars defined by the length parameter.
Sources:
https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Statistical/StDevAll
Calculation:
Default Inputs:
length=None (All), stds=[1, 2, 3], ddof=1
LR = Linear Regression
STDEV = Standard Deviation
LR = LR(close, length)
STDEV = STDEV(close, length, ddof)
for level in stds:
LOWER = LR - level * STDEV
UPPER = LR + level * STDEV
Args:
close (pd.Series): Series of 'close's
length (int): Bars from current bar. Default: None
"""
stds (list): 儲存標準偏差的列表,按照從中心線性迴歸線開始增加的順序排列。預設值為 [1,2,3]
ddof (int): Delta 自由度。在計算中使用的除數是 N - ddof,其中 N 表示元素的數量。預設值為 1
offset (int): 結果的偏移週期數。預設值為 0
# 函式引數說明,接受關鍵字引數
Kwargs:
# fillna 引數,用於填充缺失值的數值
fillna (value, optional): pd.DataFrame.fillna(value)
# fill_method 引數,指定填充方法的型別
fill_method (value, optional): Type of fill method
# 返回值說明,返回一個 pandas DataFrame 物件
Returns:
# 返回一個 pandas DataFrame 物件,包含中心 LR 和基於標準差倍數的上下 LR 線對
pd.DataFrame: Central LR, Pairs of Lower and Upper LR Lines based on
mulitples of the standard deviation. Default: returns 7 columns.
.\pandas-ta\pandas_ta\statistics\variance.py
# 設定檔案編碼為 UTF-8
# -*- coding: utf-8 -*-
# 從 pandas_ta 庫中匯入 Imports 模組
from pandas_ta import Imports
# 從 pandas_ta.utils 中匯入 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
def variance(close, length=None, ddof=None, talib=None, offset=None, **kwargs):
"""Indicator: Variance"""
# 驗證引數
# 將長度轉換為整數,如果長度存在且大於1,則為長度,否則為30
length = int(length) if length and length > 1 else 30
# 將 ddof 轉換為整數,如果 ddof 是整數且大於等於0且小於長度,則為 ddof,否則為1
ddof = int(ddof) if isinstance(ddof, int) and ddof >= 0 and ddof < length else 1
# 如果kwargs中存在"min_periods",則將其轉換為整數,否則為長度
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
# 驗證close是否為有效Series,長度為最大值(長度,min_periods)
close = verify_series(close, max(length, min_periods))
# 獲取偏移量
offset = get_offset(offset)
# 確定是否使用 talib
mode_tal = bool(talib) if isinstance(talib, bool) else True
# 如果close為None,則返回
if close is None: return
# 計算結果
# 如果 pandas_ta 已匯入 talib 並且 mode_tal 為真,則使用 talib 中的 VAR 函式計算方差
if Imports["talib"] and mode_tal:
from talib import VAR
variance = VAR(close, length)
# 否則,使用 rolling 方法計算滾動方差
else:
variance = close.rolling(length, min_periods=min_periods).var(ddof)
# 偏移結果
if offset != 0:
variance = variance.shift(offset)
# 處理填充
# 如果kwargs中存在"fillna",則填充NaN值
if "fillna" in kwargs:
variance.fillna(kwargs["fillna"], inplace=True)
# 如果kwargs中存在"fill_method",則使用指定的填充方法
if "fill_method" in kwargs:
variance.fillna(method=kwargs["fill_method"], inplace=True)
# 設定名稱和類別
variance.name = f"VAR_{length}"
variance.category = "statistics"
return variance
# 設定 variance 函式的文件字串
variance.__doc__ = \
"""Rolling Variance
Sources:
Calculation:
Default Inputs:
length=30
VARIANCE = close.rolling(length).var()
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 30
ddof (int): Delta Degrees of Freedom.
The divisor used in calculations is N - ddof,
where N represents the number of elements. Default: 0
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\statistics\zscore.py
# -*- coding: utf-8 -*-
# 從pandas_ta.overlap模組中匯入sma函式
from pandas_ta.overlap import sma
# 從本地的stdev模組中匯入stdev函式
from .stdev import stdev
# 從pandas_ta.utils模組中匯入get_offset和verify_series函式
from pandas_ta.utils import get_offset, verify_series
# 定義函式zscore,用於計算Z分數指標
def zscore(close, length=None, std=None, offset=None, **kwargs):
"""Indicator: Z Score"""
# 驗證引數
# 將length轉換為整數,如果length存在且大於1,則取其值,否則預設為30
length = int(length) if length and length > 1 else 30
# 將std轉換為浮點數,如果std存在且大於1,則取其值,否則預設為1
std = float(std) if std and std > 1 else 1
# 驗證close是否為有效的Series,長度為length
close = verify_series(close, length)
# 獲取offset值
offset = get_offset(offset)
# 如果close為空,則返回空
if close is None: return
# 計算結果
# 將std乘以stdev函式計算的標準差值
std *= stdev(close=close, length=length, **kwargs)
# 計算均值,使用sma函式計算移動平均值
mean = sma(close=close, length=length, **kwargs)
# 計算Z分數
zscore = (close - mean) / std
# 調整偏移量
if offset != 0:
zscore = zscore.shift(offset)
# 處理填充
if "fillna" in kwargs:
zscore.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
zscore.fillna(method=kwargs["fill_method"], inplace=True)
# 設定指標名稱和類別
zscore.name = f"ZS_{length}"
zscore.category = "statistics"
return zscore
# 設定zscore函式的文件字串
zscore.__doc__ = \
"""Rolling Z Score
Sources:
Calculation:
Default Inputs:
length=30, std=1
SMA = Simple Moving Average
STDEV = Standard Deviation
std = std * STDEV(close, length)
mean = SMA(close, length)
ZSCORE = (close - mean) / std
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 30
std (float): It's 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\statistics\__init__.py
# 設定檔案編碼為 UTF-8,以支援中文等非 ASCII 字元
# 匯入自定義模組中的函式,用於計算資料的不同統計量
from .entropy import entropy # 匯入 entropy 函式,用於計算資料的熵
from .kurtosis import kurtosis # 匯入 kurtosis 函式,用於計算資料的峰度
from .mad import mad # 匯入 mad 函式,用於計算資料的絕對中位差
from .median import median # 匯入 median 函式,用於計算資料的中位數
from .quantile import quantile # 匯入 quantile 函式,用於計算資料的分位數
from .skew import skew # 匯入 skew 函式,用於計算資料的偏度
from .stdev import stdev # 匯入 stdev 函式,用於計算資料的標準差
from .tos_stdevall import tos_stdevall # 匯入 tos_stdevall 函式,用於計算資料的時間序列標準差
from .variance import variance # 匯入 variance 函式,用於計算資料的方差
from .zscore import zscore # 匯入 zscore 函式,用於計算資料的 Z 分數
.\pandas-ta\pandas_ta\trend\adx.py
# -*- coding: utf-8 -*-
# 匯入所需的庫和模組
from pandas import DataFrame
from pandas_ta.overlap import ma
from pandas_ta.volatility import atr
from pandas_ta.utils import get_drift, get_offset, verify_series, zero
# 定義 ADX 指標函式
def adx(high, low, close, length=None, lensig=None, scalar=None, mamode=None, drift=None, offset=None, **kwargs):
"""Indicator: ADX"""
# 驗證引數
length = length if length and length > 0 else 14
lensig = lensig if lensig and lensig > 0 else length
mamode = mamode if isinstance(mamode, str) else "rma"
scalar = float(scalar) if scalar else 100
high = verify_series(high, length)
low = verify_series(low, length)
close = verify_series(close, length)
drift = get_drift(drift)
offset = get_offset(offset)
if high is None or low is None or close is None: return
# 計算 ATR 指標
atr_ = atr(high=high, low=low, close=close, length=length)
# 計算上升和下降動向線
up = high - high.shift(drift) # high.diff(drift)
dn = low.shift(drift) - low # low.diff(-drift).shift(drift)
pos = ((up > dn) & (up > 0)) * up
neg = ((dn > up) & (dn > 0)) * dn
pos = pos.apply(zero)
neg = neg.apply(zero)
k = scalar / atr_
dmp = k * ma(mamode, pos, length=length)
dmn = k * ma(mamode, neg, length=length)
dx = scalar * (dmp - dmn).abs() / (dmp + dmn)
adx = ma(mamode, dx, length=lensig)
# 偏移
if offset != 0:
dmp = dmp.shift(offset)
dmn = dmn.shift(offset)
adx = adx.shift(offset)
# 處理填充值
if "fillna" in kwargs:
adx.fillna(kwargs["fillna"], inplace=True)
dmp.fillna(kwargs["fillna"], inplace=True)
dmn.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
adx.fillna(method=kwargs["fill_method"], inplace=True)
dmp.fillna(method=kwargs["fill_method"], inplace=True)
dmn.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
adx.name = f"ADX_{lensig}"
dmp.name = f"DMP_{length}"
dmn.name = f"DMN_{length}"
adx.category = dmp.category = dmn.category = "trend"
# 準備返回的 DataFrame
data = {adx.name: adx, dmp.name: dmp, dmn.name: dmn}
adxdf = DataFrame(data)
adxdf.name = f"ADX_{lensig}"
adxdf.category = "trend"
return adxdf
# 設定 ADX 函式的文件字串
adx.__doc__ = \
"""Average Directional Movement (ADX)
Average Directional Movement is meant to quantify trend strength by measuring
the amount of movement in a single direction.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/average-directional-movement-adx/
TA Lib Correlation: >99%
Calculation:
DMI ADX TREND 2.0 by @TraderR0BERT, NETWORTHIE.COM
// 由 @TraderR0BERT, NETWORTHIE.COM 建立,最後更新日期為 01/26/2016
// DMI 指標
// 解析度輸入選項,用於更高/更低的時間框架
study(title="DMI ADX TREND 2.0", shorttitle="ADX TREND 2.0")
adxlen = input(14, title="ADX Smoothing")
dilen = input(14, title="DI Length")
thold = input(20, title="Threshold")
threshold = thold
//Script for Indicator
dirmov(len) =>
up = change(high)
down = -change(low)
truerange = rma(tr, len)
plus = fixnan(100 * rma(up > down and up > 0 ? up : 0, len) / truerange)
minus = fixnan(100 * rma(down > up and down > 0 ? down : 0, len) / truerange)
[plus, minus]
adx(dilen, adxlen) =>
[plus, minus] = dirmov(dilen)
sum = plus + minus
adx = 100 * rma(abs(plus - minus) / (sum == 0 ? 1 : sum), adxlen)
[adx, plus, minus]
[sig, up, down] = adx(dilen, adxlen)
osob=input(40,title="Exhaustion Level for ADX, default = 40")
col = sig >= sig[1] ? green : sig <= sig[1] ? red : gray
//Plot Definitions Current Timeframe
p1 = plot(sig, color=col, linewidth = 3, title="ADX")
p2 = plot(sig, color=col, style=circles, linewidth=3, title="ADX")
p3 = plot(up, color=blue, linewidth = 3, title="+DI")
p4 = plot(up, color=blue, style=circles, linewidth=3, title="+DI")
p5 = plot(down, color=fuchsia, linewidth = 3, title="-DI")
p6 = plot(down, color=fuchsia, style=circles, linewidth=3, title="-DI")
h1 = plot(threshold, color=black, linewidth =3, title="Threshold")
trender = (sig >= up or sig >= down) ? 1 : 0
bgcolor(trender>0?black:gray, transp=85)
//Alert Function for ADX crossing Threshold
Up_Cross = crossover(up, threshold)
alertcondition(Up_Cross, title="DMI+ cross", message="DMI+ Crossing Threshold")
Down_Cross = crossover(down, threshold)
alertcondition(Down_Cross, title="DMI- cross", message="DMI- Crossing Threshold")
# 定義函式引數
Args:
high (pd.Series): 'high' 資料序列
low (pd.Series): 'low' 資料序列
close (pd.Series): 'close' 資料序列
length (int): 週期長度,預設為14
lensig (int): 訊號長度,類似於 TradingView 的預設 ADX 長度,預設為 length
scalar (float): 放大倍數,預設為100
mamode (str): 參考 ```help(ta.ma)```py,預設為 'rma'
drift (int): 差異週期,預設為1
offset (int): 結果偏移週期數,預設為0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value) 的填充值
fill_method (value, optional): 填充方法型別
Returns:
pd.DataFrame: 包含 adx、dmp、dmn 列的資料框
.\pandas-ta\pandas_ta\trend\amat.py
# -*- coding: utf-8 -*-
# 從 pandas 庫中匯入 DataFrame 類
from pandas import DataFrame
# 從當前目錄下的 long_run 模組中匯入 long_run 函式
from .long_run import long_run
# 從當前目錄下的 short_run 模組中匯入 short_run 函式
from .short_run import short_run
# 從 pandas_ta 包中的 overlap 模組中匯入 ma 函式
from pandas_ta.overlap import ma
# 從 pandas_ta 包中的 utils 模組中匯入 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 定義函式 amat,用於計算 Archer Moving Averages Trends (AMAT) 指標
def amat(close=None, fast=None, slow=None, lookback=None, mamode=None, offset=None, **kwargs):
"""Indicator: Archer Moving Averages Trends (AMAT)"""
# 驗證引數的有效性,如果未提供則使用預設值
fast = int(fast) if fast and fast > 0 else 8
slow = int(slow) if slow and slow > 0 else 21
lookback = int(lookback) if lookback and lookback > 0 else 2
# 將 mamode 轉換為小寫字串,如果未提供則使用預設值 "ema"
mamode = mamode.lower() if isinstance(mamode, str) else "ema"
# 驗證 close 引數,確保長度足夠用於計算指標
close = verify_series(close, max(fast, slow, lookback))
# 獲取偏移量
offset = get_offset(offset)
# 如果 kwargs 中包含 "length" 鍵,則移除它
if "length" in kwargs: kwargs.pop("length")
# 如果未提供 close 引數,則返回空值
if close is None: return
# 計算快速移動平均線和慢速移動平均線
fast_ma = ma(mamode, close, length=fast, **kwargs)
slow_ma = ma(mamode, close, length=slow, **kwargs)
# 計算長期和短期執行趨勢
mas_long = long_run(fast_ma, slow_ma, length=lookback)
mas_short = short_run(fast_ma, slow_ma, length=lookback)
# 對結果進行偏移處理
if offset != 0:
mas_long = mas_long.shift(offset)
mas_short = mas_short.shift(offset)
# 如果 kwargs 中包含 "fillna" 鍵,則使用指定的值填充缺失值
if "fillna" in kwargs:
mas_long.fillna(kwargs["fillna"], inplace=True)
mas_short.fillna(kwargs["fillna"], inplace=True)
# 如果 kwargs 中包含 "fill_method" 鍵,則使用指定的填充方法填充缺失值
if "fill_method" in kwargs:
mas_long.fillna(method=kwargs["fill_method"], inplace=True)
mas_short.fillna(method=kwargs["fill_method"], inplace=True)
# 準備要返回的 DataFrame
amatdf = DataFrame({
f"AMAT{mamode[0]}_LR_{fast}_{slow}_{lookback}": mas_long,
f"AMAT{mamode[0]}_SR_{fast}_{slow}_{lookback}": mas_short
})
# 設定 DataFrame 的名稱和類別
amatdf.name = f"AMAT{mamode[0]}_{fast}_{slow}_{lookback}"
amatdf.category = "trend"
# 返回結果 DataFrame
return amatdf
.\pandas-ta\pandas_ta\trend\aroon.py
# -*- coding: utf-8 -*-
# 從 pandas 庫中匯入 DataFrame 類
from pandas import DataFrame
# 從 pandas_ta 庫中匯入 Imports 模組
from pandas_ta import Imports
# 從 pandas_ta.utils 模組中匯入 get_offset, verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 從 pandas_ta.utils 模組中匯入 recent_maximum_index, recent_minimum_index 函式
from pandas_ta.utils import recent_maximum_index, recent_minimum_index
# 定義函式 aroon,計算 Aroon 和 Aroon Oscillator 指標
def aroon(high, low, length=None, scalar=None, talib=None, offset=None, **kwargs):
"""Indicator: Aroon & Aroon Oscillator"""
# 驗證引數
length = length if length and length > 0 else 14
scalar = float(scalar) if scalar else 100
high = verify_series(high, length)
low = verify_series(low, length)
offset = get_offset(offset)
mode_tal = bool(talib) if isinstance(talib, bool) else True
if high is None or low is None: return
# 計算結果
if Imports["talib"] and mode_tal:
from talib import AROON, AROONOSC
aroon_down, aroon_up = AROON(high, low, length)
aroon_osc = AROONOSC(high, low, length)
else:
periods_from_hh = high.rolling(length + 1).apply(recent_maximum_index, raw=True)
periods_from_ll = low.rolling(length + 1).apply(recent_minimum_index, raw=True)
aroon_up = aroon_down = scalar
aroon_up *= 1 - (periods_from_hh / length)
aroon_down *= 1 - (periods_from_ll / length)
aroon_osc = aroon_up - aroon_down
# 處理填充
if "fillna" in kwargs:
aroon_up.fillna(kwargs["fillna"], inplace=True)
aroon_down.fillna(kwargs["fillna"], inplace=True)
aroon_osc.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
aroon_up.fillna(method=kwargs["fill_method"], inplace=True)
aroon_down.fillna(method=kwargs["fill_method"], inplace=True)
aroon_osc.fillna(method=kwargs["fill_method"], inplace=True)
# 偏移
if offset != 0:
aroon_up = aroon_up.shift(offset)
aroon_down = aroon_down.shift(offset)
aroon_osc = aroon_osc.shift(offset)
# 命名和分類
aroon_up.name = f"AROONU_{length}"
aroon_down.name = f"AROOND_{length}"
aroon_osc.name = f"AROONOSC_{length}"
aroon_down.category = aroon_up.category = aroon_osc.category = "trend"
# 準備要返回的 DataFrame
data = {
aroon_down.name: aroon_down,
aroon_up.name: aroon_up,
aroon_osc.name: aroon_osc,
}
aroondf = DataFrame(data)
aroondf.name = f"AROON_{length}"
aroondf.category = aroon_down.category
return aroondf
# 設定函式 aroon 的文件字串
aroon.__doc__ = \
"""Aroon & Aroon Oscillator (AROON)
Aroon attempts to identify if a security is trending and how strong.
Sources:
https://www.tradingview.com/wiki/Aroon
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/aroon-ar/
Calculation:
Default Inputs:
length=1, scalar=100
recent_maximum_index(x): return int(np.argmax(x[::-1]))
recent_minimum_index(x): return int(np.argmin(x[::-1]))
periods_from_hh = high.rolling(length + 1).apply(recent_maximum_index, raw=True)
"""
# 計算 Aroon 指標中的上升線,使用公式:scalar * (1 - (periods_from_hh / length))
AROON_UP = scalar * (1 - (periods_from_hh / length))
# 計算 Aroon 指標中的下降線,使用公式:scalar * (1 - (periods_from_ll / length))
periods_from_ll = low.rolling(length + 1).apply(recent_minimum_index, raw=True)
AROON_DN = scalar * (1 - (periods_from_ll / length))
# 計算 Aroon 指標的震盪值,使用公式:AROON_UP - AROON_DN
AROON_OSC = AROON_UP - AROON_DN
# 定義函式引數
Args:
close (pd.Series): 包含'close'價格資料的Series
length (int): 計算指標的週期,預設為14
scalar (float): 放大倍數,預設為100
talib (bool): 如果安裝了TA Lib並且talib為True,則返回TA Lib版本,預設為True
offset (int): 結果的偏移週期數,預設為0
# 定義函式關鍵字引數
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)的填充值
fill_method (value, optional): 填充方法的型別
# 返回值
Returns:
pd.DataFrame: 包含aroon_up、aroon_down、aroon_osc列的DataFrame
.\pandas-ta\pandas_ta\trend\chop.py
# -*- coding: utf-8 -*-
# 從 numpy 庫中匯入 log10 函式並重新命名為 npLog10
from numpy import log10 as npLog10
# 從 numpy 庫中匯入 log 函式並重新命名為 npLn
from numpy import log as npLn
# 從 pandas_ta 庫中匯入 volatility 模組中的 atr 函式
from pandas_ta.volatility import atr
# 從 pandas_ta 庫中匯入 utils 模組中的 get_drift, get_offset, verify_series 函式
from pandas_ta.utils import get_drift, get_offset, verify_series
# 定義函式 chop,計算 Choppiness Index (CHOP)
def chop(high, low, close, length=None, atr_length=None, ln=None, scalar=None, drift=None, offset=None, **kwargs):
"""Indicator: Choppiness Index (CHOP)"""
# 驗證引數
length = int(length) if length and length > 0 else 14
atr_length = int(atr_length) if atr_length is not None and atr_length > 0 else 1
ln = bool(ln) if isinstance(ln, bool) else False
scalar = float(scalar) if scalar else 100
high = verify_series(high, length)
low = verify_series(low, length)
close = verify_series(close, length)
drift = get_drift(drift)
offset = get_offset(offset)
# 如果 high、low、close 中有任何一個為 None,則返回
if high is None or low is None or close is None: return
# 計算結果
diff = high.rolling(length).max() - low.rolling(length).min()
atr_ = atr(high=high, low=low, close=close, length=atr_length)
atr_sum = atr_.rolling(length).sum()
chop = scalar
if ln:
chop *= (npLn(atr_sum) - npLn(diff)) / npLn(length)
else:
chop *= (npLog10(atr_sum) - npLog10(diff)) / npLog10(length)
# 偏移結果
if offset != 0:
chop = chop.shift(offset)
# 處理填充值
if "fillna" in kwargs:
chop.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
chop.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
chop.name = f"CHOP{'ln' if ln else ''}_{length}_{atr_length}_{scalar}"
chop.category = "trend"
return chop
# 設定 chop 函式的文件字串
chop.__doc__ = \
"""Choppiness Index (CHOP)
The Choppiness Index was created by Australian commodity trader
E.W. Dreiss and is designed to determine if the market is choppy
(trading sideways) or not choppy (trading within a trend in either
direction). Values closer to 100 implies the underlying is choppier
whereas values closer to 0 implies the underlying is trending.
Sources:
https://www.tradingview.com/scripts/choppinessindex/
https://www.motivewave.com/studies/choppiness_index.htm
Calculation:
Default Inputs:
length=14, scalar=100, drift=1
HH = high.rolling(length).max()
LL = low.rolling(length).min()
ATR_SUM = SUM(ATR(drift), length)
CHOP = scalar * (LOG10(ATR_SUM) - LOG10(HH - LL))
CHOP /= LOG10(length)
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
atr_length (int): Length for ATR. Default: 1
ln (bool): If True, uses ln otherwise log10. Default: False
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:
"""
# 建立一個 Pandas Series 物件,表示生成了一個新特徵
pd.Series: New feature generated.
# 這是一個空的字串,通常用作多行註釋的起始
.\pandas-ta\pandas_ta\trend\cksp.py
# -*- coding: utf-8 -*-
# 從 pandas 庫中匯入 DataFrame 類
from pandas import DataFrame
# 從 pandas_ta 庫中匯入 atr 函式
from pandas_ta.volatility import atr
# 從 pandas_ta 庫中匯入 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 定義函式 cksp,計算 Chande Kroll Stop (CKSP) 指標
def cksp(high, low, close, p=None, x=None, q=None, tvmode=None, offset=None, **kwargs):
"""Indicator: Chande Kroll Stop (CKSP)"""
# 驗證引數
p = int(p) if p and p > 0 else 10
x = float(x) if x and x > 0 else 1 if tvmode is True else 3
q = int(q) if q and q > 0 else 9 if tvmode is True else 20
_length = max(p, q, x)
high = verify_series(high, _length)
low = verify_series(low, _length)
close = verify_series(close, _length)
if high is None or low is None or close is None: return
offset = get_offset(offset)
tvmode = tvmode if isinstance(tvmode, bool) else True
mamode = "rma" if tvmode is True else "sma"
# 計算結果
atr_ = atr(high=high, low=low, close=close, length=p, mamode=mamode)
long_stop_ = high.rolling(p).max() - x * atr_
long_stop = long_stop_.rolling(q).max()
short_stop_ = low.rolling(p).min() + x * atr_
short_stop = short_stop_.rolling(q).min()
# 偏移
if offset != 0:
long_stop = long_stop.shift(offset)
short_stop = short_stop.shift(offset)
# 處理填充
if "fillna" in kwargs:
long_stop.fillna(kwargs["fillna"], inplace=True)
short_stop.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
long_stop.fillna(method=kwargs["fill_method"], inplace=True)
short_stop.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
_props = f"_{p}_{x}_{q}"
long_stop.name = f"CKSPl{_props}"
short_stop.name = f"CKSPs{_props}"
long_stop.category = short_stop.category = "trend"
# 準備返回的 DataFrame
ckspdf = DataFrame({long_stop.name: long_stop, short_stop.name: short_stop})
ckspdf.name = f"CKSP{_props}"
ckspdf.category = long_stop.category
return ckspdf
# 設定函式 cksp 的文件字串
cksp.__doc__ = \
"""Chande Kroll Stop (CKSP)
The Tushar Chande and Stanley Kroll in their book
“The New Technical Trader”. It is a trend-following indicator,
identifying your stop by calculating the average true range of
the recent market volatility. The indicator defaults to the implementation
found on tradingview but it provides the original book implementation as well,
which differs by the default periods and moving average mode. While the trading
view implementation uses the Welles Wilder moving average, the book uses a
simple moving average.
Sources:
https://www.multicharts.com/discussion/viewtopic.php?t=48914
"The New Technical Trader", Wikey 1st ed. ISBN 9780471597803, page 95
Calculation:
Default Inputs:
p=10, x=1, q=9, tvmode=True
ATR = Average True Range
LS0 = high.rolling(p).max() - x * ATR(length=p)
LS = LS0.rolling(q).max()
SS0 = high.rolling(p).min() + x * ATR(length=p)
SS = SS0.rolling(q).min()
Args:
"""
# 'close'是一個包含收盤價的Series物件
# p是ATR和第一個停止期的值,以整數表示。在兩種模式下預設值均為10
# x是ATR的標量值,在Trading View模式下預設值為1,在其他模式下預設值為3
# q是第二個停止期的值,以整數表示。在Trading View模式下預設值為9,在其他模式下預設值為20
# tvmode是一個布林值,表示是否使用Trading View模式或書中實現模式。預設為True表示使用Trading View模式
# offset是結果的偏移週期數。預設值為0
# 定義函式的引數列表,這裡使用了可選引數
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value) # 填充缺失值的數值
fill_method (value, optional): Type of fill method # 填充方法的型別
# 返回值說明
Returns:
pd.DataFrame: long and short columns. # 返回一個包含長列和短列的 Pandas 資料幀
.\pandas-ta\pandas_ta\trend\decay.py
# -*- coding: utf-8 -*-
# 從 numpy 匯入 exp 函式並重新命名為 npExp
from numpy import exp as npExp
# 從 pandas 匯入 DataFrame 類
from pandas import DataFrame
# 從 pandas_ta.utils 匯入 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
def decay(close, kind=None, length=None, mode=None, offset=None, **kwargs):
"""Indicator: Decay"""
# 驗證引數
# 如果 length 存在且大於 0,則轉換為整數,否則設定為預設值 5
length = int(length) if length and length > 0 else 5
# 如果 mode 是字串,則轉換為小寫,否則設定為預設值 "linear"
mode = mode.lower() if isinstance(mode, str) else "linear"
# 驗證 close 是否是有效的 Series,長度為 length
close = verify_series(close, length)
# 獲取偏移量
offset = get_offset(offset)
# 如果 close 為空,則返回 None
if close is None: return
# 計算結果
# 預設模式為線性模式
_mode = "L"
# 如果 mode 是 "exp" 或 kind 是 "exponential",則使用指數模式
if mode == "exp" or kind == "exponential":
_mode = "EXP"
# 計算差異,利用指數函式 exp(-length)
diff = close.shift(1) - npExp(-length)
else: # 預設為 "linear"
# 計算差異,利用線性函式 (1 / length)
diff = close.shift(1) - (1 / length)
# 將第一個元素設定為 close 的第一個值
diff[0] = close[0]
# 建立 DataFrame,包含 close、diff 和 0 列
tdf = DataFrame({"close": close, "diff": diff, "0": 0})
# 計算最大值
ld = tdf.max(axis=1)
# 偏移結果
if offset != 0:
ld = ld.shift(offset)
# 處理填充
# 如果 kwargs 中包含 "fillna",則使用指定值填充缺失值
if "fillna" in kwargs:
ld.fillna(kwargs["fillna"], inplace=True)
# 如果 kwargs 中包含 "fill_method",則使用指定的填充方法
if "fill_method" in kwargs:
ld.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
# 設定 Series 的名稱為模式和長度的組合
ld.name = f"{_mode}DECAY_{length}"
# 設定 Series 的分類為 "trend"
ld.category = "trend"
return ld
# 設定 decay 函式的文件字串
decay.__doc__ = \
"""Decay
Creates a decay moving forward from prior signals like crosses. The default is
"linear". Exponential is optional as "exponential" or "exp".
Sources:
https://tulipindicators.org/decay
Calculation:
Default Inputs:
length=5, mode=None
if mode == "exponential" or mode == "exp":
max(close, close[-1] - exp(-length), 0)
else:
max(close, close[-1] - (1 / length), 0)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
mode (str): If 'exp' then "exponential" decay. Default: 'linear'
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.
"""