.\pandas-ta\pandas_ta\momentum\stc.py
# -*- coding: utf-8 -*-
從 pandas 庫中匯入 DataFrame 和 Series 類
從 pandas_ta.overlap 模組中匯入 ema 函式
從 pandas_ta.utils 模組中匯入 get_offset、non_zero_range 和 verify_series 函式
# 定義函式:Schaff Trend Cycle (STC)
def stc(close, tclength=None, fast=None, slow=None, factor=None, offset=None, **kwargs):
# 驗證引數
tclength = int(tclength) if tclength and tclength > 0 else 10
fast = int(fast) if fast and fast > 0 else 12
slow = int(slow) if slow and slow > 0 else 26
factor = float(factor) if factor and factor > 0 else 0.5
# 如果慢線小於快線,則交換它們的值
if slow < fast:
fast, slow = slow, fast
# 計算所需資料的長度,取最大值
_length = max(tclength, fast, slow)
# 驗證收盤價資料,返回驗證後的 Series 物件
close = verify_series(close, _length)
# 獲取偏移量
offset = get_offset(offset)
# 如果收盤價為 None,則返回
if close is None: return
# kwargs 允許傳遞三個更多的 Series(ma1、ma2 和 osc),這些可以在這裡傳遞,
# ma1 和 ma2 輸入會抵消內部的 ema 計算,osc 替代了兩個 ma。
ma1 = kwargs.pop("ma1", False)
ma2 = kwargs.pop("ma2", False)
osc = kwargs.pop("osc", False)
# 3 種不同的計算模式..
if isinstance(ma1, Series) and isinstance(ma2, Series) and not osc:
# 驗證輸入的兩個外部 Series 物件
ma1 = verify_series(ma1, _length)
ma2 = verify_series(ma2, _length)
# 如果其中一個為 None,則返回
if ma1 is None or ma2 is None: return
# 根據外部提供的 Series 計算結果
xmacd = ma1 - ma2
# 呼叫共享計算函式
pff, pf = schaff_tc(close, xmacd, tclength, factor)
elif isinstance(osc, Series):
# 驗證輸入的振盪器 Series 物件
osc = verify_series(osc, _length)
# 如果為 None,則返回
if osc is None: return
# 根據提供的振盪器計算結果(應在 0 軸附近)
xmacd = osc
# 呼叫共享計算函式
pff, pf = schaff_tc(close, xmacd, tclength, factor)
else:
# 計算結果..(傳統/完整)
# MACD 線
fastma = ema(close, length=fast)
slowma = ema(close, length=slow)
xmacd = fastma - slowma
# 呼叫共享計算函式
pff, pf = schaff_tc(close, xmacd, tclength, factor)
# 結果 Series
stc = Series(pff, index=close.index)
macd = Series(xmacd, index=close.index)
stoch = Series(pf, index=close.index)
# 偏移
if offset != 0:
stc = stc.shift(offset)
macd = macd.shift(offset)
stoch = stoch.shift(offset)
# 填充缺失值
if "fillna" in kwargs:
stc.fillna(kwargs["fillna"], inplace=True)
macd.fillna(kwargs["fillna"], inplace=True)
stoch.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
stc.fillna(method=kwargs["fill_method"], inplace=True)
macd.fillna(method=kwargs["fill_method"], inplace=True)
stoch.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
_props = f"_{tclength}_{fast}_{slow}_{factor}"
stc.name = f"STC{_props}"
macd.name = f"STCmacd{_props}"
# 設定 stoch 物件的名稱屬性為包含 _props 的字串
stoch.name = f"STCstoch{_props}"
# 設定 stc 和 macd 物件的 category 屬性為 "momentum"
stc.category = macd.category = stoch.category ="momentum"
# 準備要返回的 DataFrame
# 建立一個字典,包含 stc.name、macd.name 和 stoch.name 作為鍵,對應的物件為值
data = {stc.name: stc, macd.name: macd, stoch.name: stoch}
# 用 data 字典建立 DataFrame 物件
df = DataFrame(data)
# 設定 DataFrame 物件的名稱屬性為包含 _props 的字串
df.name = f"STC{_props}"
# 設定 DataFrame 物件的 category 屬性為 stc 物件的 category 屬性
df.category = stc.category
# 返回 DataFrame 物件
return df
# 設定 stc 的文件字串,描述 Schaff Trend Cycle(STC)指標的計算方法和用法
stc.__doc__ = \
"""Schaff Trend Cycle (STC)
The Schaff Trend Cycle is an evolution of the popular MACD incorportating two
cascaded stochastic calculations with additional smoothing.
The STC returns also the beginning MACD result as well as the result after the
first stochastic including its smoothing. This implementation has been extended
for Pandas TA to also allow for separatly feeding any other two moving Averages
(as ma1 and ma2) or to skip this to feed an oscillator (osc), based on which the
Schaff Trend Cycle should be calculated.
Feed external moving averages:
Internally calculation..
stc = ta.stc(close=df["close"], tclen=stc_tclen, fast=ma1_interval, slow=ma2_interval, factor=stc_factor)
becomes..
extMa1 = df.ta.zlma(close=df["close"], length=ma1_interval, append=True)
extMa2 = df.ta.ema(close=df["close"], length=ma2_interval, append=True)
stc = ta.stc(close=df["close"], tclen=stc_tclen, ma1=extMa1, ma2=extMa2, factor=stc_factor)
The same goes for osc=, which allows the input of an externally calculated oscillator, overriding ma1 & ma2.
Sources:
Implemented by rengel8 based on work found here:
https://www.prorealcode.com/prorealtime-indicators/schaff-trend-cycle2/
Calculation:
STCmacd = Moving Average Convergance/Divergance or Oscillator
STCstoch = Intermediate Stochastic of MACD/Osc.
2nd Stochastic including filtering with results in the
STC = Schaff Trend Cycle
Args:
close (pd.Series): Series of 'close's, used for indexing Series, mandatory
tclen (int): SchaffTC Signal-Line length. Default: 10 (adjust to the half of cycle)
fast (int): The short period. Default: 12
slow (int): The long period. Default: 26
factor (float): smoothing factor for last stoch. calculation. Default: 0.5
offset (int): How many periods to offset the result. Default: 0
Kwargs:
ma1: 1st moving average provided externally (mandatory in conjuction with ma2)
ma2: 2nd moving average provided externally (mandatory in conjuction with ma1)
osc: an externally feeded osillator
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: stc, macd, stoch
"""
# 定義 Schaff Trend Cycle(STC)計算函式
def schaff_tc(close, xmacd, tclength, factor):
# 實際計算部分,這部分計算適用於不同的操作模式
# 1. MACD 的 Stochastic
# 計算區間 tclen 內 xmacd 的最小值
lowest_xmacd = xmacd.rolling(tclength).min() # min value in interval tclen
# 計算區間 tclen 內 xmacd 的範圍(最大值 - 最小值)
xmacd_range = non_zero_range(xmacd.rolling(tclength).max(), lowest_xmacd)
# 獲取 xmacd 的長度
m = len(xmacd)
# 計算 MACD 的快速 %K
# 初始化 stoch1 和 pf 列表
stoch1, pf = list(xmacd), list(xmacd)
# 第一個元素的值為 0
stoch1[0], pf[0] = 0, 0
# 迴圈計算 stoch1 和 pf 列表中的值
for i in range(1, m):
# 如果 lowest_xmacd[i] 大於 0,則計算快速 %K
if lowest_xmacd[i] > 0:
stoch1[i] = 100 * ((xmacd[i] - lowest_xmacd[i]) / xmacd_range[i])
else:
# 否則保持前一個值不變
stoch1[i] = stoch1[i - 1]
# 計算平滑後的 %D
pf[i] = round(pf[i - 1] + (factor * (stoch1[i] - pf[i - 1])), 8)
# 將 pf 轉換為 Series 型別,並以 close 的索引為索引
pf = Series(pf, index=close.index)
# 計算平滑後的 Percent Fast D, 'PF' 的隨機指標
# 計算滾動視窗為 tclength 的最小值
lowest_pf = pf.rolling(tclength).min()
# 計算 pf 在滾動視窗為 tclength 的範圍內的非零範圍
pf_range = non_zero_range(pf.rolling(tclength).max(), lowest_pf)
# 計算 % Fast K of PF
stoch2, pff = list(xmacd), list(xmacd)
stoch2[0], pff[0] = 0, 0
for i in range(1, m):
if pf_range[i] > 0:
# 計算 % Fast K of PF
stoch2[i] = 100 * ((pf[i] - lowest_pf[i]) / pf_range[i])
else:
stoch2[i] = stoch2[i - 1]
# 計算平滑後的 % Fast D of PF
# 使用平滑因子 factor 進行平滑計算
pff[i] = round(pff[i - 1] + (factor * (stoch2[i] - pff[i - 1])), 8)
# 返回平滑後的 % Fast D of PF 和原始的 PF
return [pff, pf]
# `.\pandas-ta\pandas_ta\momentum\stoch.py`
```py
# -*- coding: utf-8 -*-
# 匯入DataFrame類
from pandas import DataFrame
# 從pandas_ta.overlap模組中匯入ma函式
from pandas_ta.overlap import ma
# 從pandas_ta.utils模組中匯入get_offset、non_zero_range和verify_series函式
from pandas_ta.utils import get_offset, non_zero_range, verify_series
# 定義Stochastic Oscillator (STOCH)函式
def stoch(high, low, close, k=None, d=None, smooth_k=None, mamode=None, offset=None, **kwargs):
"""Indicator: Stochastic Oscillator (STOCH)"""
# 校驗引數
# 如果k為正數則使用k,否則預設為14
k = k if k and k > 0 else 14
# 如果d為正數則使用d,否則預設為3
d = d if d and d > 0 else 3
# 如果smooth_k為正數則使用smooth_k,否則預設為3
smooth_k = smooth_k if smooth_k and smooth_k > 0 else 3
# 計算_max(k, d, smooth_k)
_length = max(k, d, smooth_k)
# 校驗high、low和close的長度是否為_length
high = verify_series(high, _length)
low = verify_series(low, _length)
close = verify_series(close, _length)
# 獲取offset值
offset = get_offset(offset)
# 如果mamode不是字串則設為"sma"
mamode = mamode if isinstance(mamode, str) else "sma"
# 如果high、low或close有任何一個為None,則返回空值
if high is None or low is None or close is None: return
# 計算結果
# 計算過去k個週期的最低值
lowest_low = low.rolling(k).min()
# 計算過去k個週期的最高值
highest_high = high.rolling(k).max()
# 計算stoch值
stoch = 100 * (close - lowest_low)
stoch /= non_zero_range(highest_high, lowest_low)
# 計算stoch_k和stoch_d
stoch_k = ma(mamode, stoch.loc[stoch.first_valid_index():,], length=smooth_k)
stoch_d = ma(mamode, stoch_k.loc[stoch_k.first_valid_index():,], length=d)
# 偏移處理
if offset != 0:
stoch_k = stoch_k.shift(offset)
stoch_d = stoch_d.shift(offset)
# 處理填充值
if "fillna" in kwargs:
stoch_k.fillna(kwargs["fillna"], inplace=True)
stoch_d.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
stoch_k.fillna(method=kwargs["fill_method"], inplace=True)
stoch_d.fillna(method=kwargs["fill_method"], inplace=True)
# 設定名稱和分類
_name = "STOCH"
_props = f"_{k}_{d}_{smooth_k}"
stoch_k.name = f"{_name}k{_props}"
stoch_d.name = f"{_name}d{_props}"
stoch_k.category = stoch_d.category = "momentum"
# 準備要返回的DataFrame
data = {stoch_k.name: stoch_k, stoch_d.name: stoch_d}
df = DataFrame(data)
df.name = f"{_name}{_props}"
df.category = stoch_k.category
return df
# 設定stoch函式的文件字串
stoch.__doc__ = \
"""Stochastic (STOCH)
The Stochastic Oscillator (STOCH) was developed by George Lane in the 1950's.
He believed this indicator was a good way to measure momentum because changes in
momentum precede changes in price.
It is a range-bound oscillator with two lines moving between 0 and 100.
The first line (%K) displays the current close in relation to the period's
high/low range. The second line (%D) is a Simple Moving Average of the %K line.
The most common choices are a 14 period %K and a 3 period SMA for %D.
Sources:
https://www.tradingview.com/wiki/Stochastic_(STOCH)
https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=332&Name=KD_-_Slow
Calculation:
Default Inputs:
k=14, d=3, smooth_k=3
SMA = Simple Moving Average
LL = low for last k periods
HH = high for last k periods
STOCH = 100 * (close - LL) / (HH - LL)
STOCHk = SMA(STOCH, smooth_k)
STOCHd = SMA(FASTK, d)
Args:
high (pd.Series): Series of 'high's
"""
# 表示傳入函式的引數,分別為低價序列
low (pd.Series): Series of 'low's
# 表示傳入函式的引數,分別為收盤價序列
close (pd.Series): Series of 'close's
# 表示傳入函式的引數,表示快速 %K 的週期,預設為 14
k (int): The Fast %K period. Default: 14
# 表示傳入函式的引數,表示慢速 %K 的週期,預設為 3
d (int): The Slow %K period. Default: 3
# 表示傳入函式的引數,表示慢速 %D 的週期,預設為 3
smooth_k (int): The Slow %D period. Default: 3
# 表示傳入函式的引數,參見 ta.ma 的幫助文件。預設為 'sma'
mamode (str): See ```help(ta.ma)```py. Default: 'sma'
# 表示傳入函式的引數,表示結果的偏移週期數,預設為 0
offset (int): How many periods to offset the result. Default: 0
# 引數說明:
# - fillna (value, optional): 使用 value 對 pd.DataFrame 進行填充
# - fill_method (value, optional): 填充方法的型別
# 返回值:
# - 返回一個 pd.DataFrame,包含 %K 和 %D 列
.\pandas-ta\pandas_ta\momentum\stochrsi.py
# -*- coding: utf-8 -*-
# 從 pandas 庫中匯入 DataFrame 類
from pandas import DataFrame
# 從 .rsi 模組中匯入 rsi 函式
from .rsi import rsi
# 從 pandas_ta.overlap 模組中匯入 ma 函式
from pandas_ta.overlap import ma
# 從 pandas_ta.utils 模組中匯入 get_offset, non_zero_range, verify_series 函式
from pandas_ta.utils import get_offset, non_zero_range, verify_series
# 定義函式 stochrsi,計算 Stochastic RSI Oscillator (STOCHRSI)
def stochrsi(close, length=None, rsi_length=None, k=None, d=None, mamode=None, offset=None, **kwargs):
"""Indicator: Stochastic RSI Oscillator (STOCHRSI)"""
# 校驗引數
length = length if length and length > 0 else 14
rsi_length = rsi_length if rsi_length and rsi_length > 0 else 14
k = k if k and k > 0 else 3
d = d if d and d > 0 else 3
# 校驗 close 序列
close = verify_series(close, max(length, rsi_length, k, d))
offset = get_offset(offset)
# 確定 mamode 預設為 "sma",如果 mamode 不是字串則設為 "sma"
mamode = mamode if isinstance(mamode, str) else "sma"
# 如果 close 為 None,返回空值
if close is None: return
# 計算結果
# 計算 RSI
rsi_ = rsi(close, length=rsi_length)
# 計算最低 RSI
lowest_rsi = rsi_.rolling(length).min()
# 計算最高 RSI
highest_rsi = rsi_.rolling(length).max()
# 計算 stoch 值
stoch = 100 * (rsi_ - lowest_rsi)
stoch /= non_zero_range(highest_rsi, lowest_rsi)
# 計算 STOCHRSI 的 %K 線和 %D 線
stochrsi_k = ma(mamode, stoch, length=k)
stochrsi_d = ma(mamode, stochrsi_k, length=d)
# 偏移
if offset != 0:
stochrsi_k = stochrsi_k.shift(offset)
stochrsi_d = stochrsi_d.shift(offset)
# 處理填充值
if "fillna" in kwargs:
stochrsi_k.fillna(kwargs["fillna"], inplace=True)
stochrsi_d.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
stochrsi_k.fillna(method=kwargs["fill_method"], inplace=True)
stochrsi_d.fillna(method=kwargs["fill_method"], inplace=True)
# 命名並分類
_name = "STOCHRSI"
_props = f"_{length}_{rsi_length}_{k}_{d}"
stochrsi_k.name = f"{_name}k{_props}"
stochrsi_d.name = f"{_name}d{_props}"
stochrsi_k.category = stochrsi_d.category = "momentum"
# 準備返回的 DataFrame
data = {stochrsi_k.name: stochrsi_k, stochrsi_d.name: stochrsi_d}
df = DataFrame(data)
df.name = f"{_name}{_props}"
df.category = stochrsi_k.category
return df
# 設定 stochrsi 函式的文件字串
stochrsi.__doc__ = \
"""Stochastic (STOCHRSI)
"Stochastic RSI and Dynamic Momentum Index" was created by Tushar Chande and Stanley Kroll and published in Stock & Commodities V.11:5 (189-199)
It is a range-bound oscillator with two lines moving between 0 and 100.
The first line (%K) displays the current RSI in relation to the period's
high/low range. The second line (%D) is a Simple Moving Average of the %K line.
The most common choices are a 14 period %K and a 3 period SMA for %D.
Sources:
https://www.tradingview.com/wiki/Stochastic_(STOCH)
Calculation:
Default Inputs:
length=14, rsi_length=14, k=3, d=3
RSI = Relative Strength Index
SMA = Simple Moving Average
RSI = RSI(high, low, close, rsi_length)
LL = lowest RSI for last rsi_length periods
HH = highest RSI for last rsi_length periods
STOCHRSI = 100 * (RSI - LL) / (HH - LL)
STOCHRSIk = SMA(STOCHRSI, k)
STOCHRSId = SMA(STOCHRSIk, d)
Args:
high (pd.Series): Series of 'high's
"""
low (pd.Series): 儲存股價的最低價序列
close (pd.Series): 儲存股價的收盤價序列
length (int): STOCHRSI 的週期。預設為 14
rsi_length (int): RSI 的週期。預設為 14
k (int): 快速 %K 的週期。預設為 3
d (int): 慢速 %K 的週期。預設為 3
mamode (str): 檢視 ```help(ta.ma)```py。預設為 'sma'(簡單移動平均)
offset (int): 結果偏移的週期數。預設為 0
# 引數說明部分,描述函式的引數和返回值
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
# 返回值說明部分,描述函式返回的資料型別和列名
Returns:
pd.DataFrame: RSI %K, RSI %D columns.
.\pandas-ta\pandas_ta\momentum\td_seq.py
# -*- coding: utf-8 -*-
# 從 numpy 庫中匯入 where 函式並重新命名為 npWhere
from numpy import where as npWhere
# 從 pandas 庫中匯入 DataFrame 和 Series 類
from pandas import DataFrame, Series
# 從 pandas_ta.utils 模組中匯入 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 定義函式 td_seq,用於計算 Tom Demark Sequential(TD_SEQ)指標
def td_seq(close, asint=None, offset=None, **kwargs):
"""Indicator: Tom Demark Sequential (TD_SEQ)"""
# 驗證引數 close 是否為有效的 Series 物件
close = verify_series(close)
# 獲取偏移量
offset = get_offset(offset)
# 如果 asint 不為布林值,則設定為 False
asint = asint if isinstance(asint, bool) else False
# 獲取引數中的 show_all,如果不存在則設定預設值為 True
show_all = kwargs.setdefault("show_all", True)
# 定義函式 true_sequence_count,用於計算連續的真值序列數量
def true_sequence_count(series: Series):
# 找到最後一個為 False 的索引
index = series.where(series == False).last_valid_index()
if index is None:
# 如果索引為空,則返回序列的總數
return series.count()
else:
# 否則,返回索引之後的序列數量
s = series[series.index > index]
return s.count()
# 定義函式 calc_td,用於計算 TD_SEQ
def calc_td(series: Series, direction: str, show_all: bool):
# 計算 TD_SEQ 的布林值
td_bool = series.diff(4) > 0 if direction=="up" else series.diff(4) < 0
# 根據布林值計算 TD_SEQ 數值
td_num = npWhere(
td_bool, td_bool.rolling(13, min_periods=0).apply(true_sequence_count), 0
)
td_num = Series(td_num)
if show_all:
# 如果 show_all 為 True,則保留所有 TD_SEQ 值
td_num = td_num.mask(td_num == 0)
else:
# 否則,只保留在 6 到 9 之間的 TD_SEQ 值
td_num = td_num.mask(~td_num.between(6,9))
return td_num
# 計算上升序列的 TD_SEQ
up_seq = calc_td(close, "up", show_all)
# 計算下降序列的 TD_SEQ
down_seq = calc_td(close, "down", show_all)
# 如果需要將結果轉換為整數
if asint:
if up_seq.hasnans and down_seq.hasnans:
# 填充缺失值為 0
up_seq.fillna(0, inplace=True)
down_seq.fillna(0, inplace=True)
# 轉換結果為整數型別
up_seq = up_seq.astype(int)
down_seq = down_seq.astype(int)
# 如果偏移量不為 0
if offset != 0:
# 對結果進行偏移
up_seq = up_seq.shift(offset)
down_seq = down_seq.shift(offset)
# 處理填充值
if "fillna" in kwargs:
up_seq.fillna(kwargs["fillna"], inplace=True)
down_seq.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
up_seq.fillna(method=kwargs["fill_method"], inplace=True)
down_seq.fillna(method=kwargs["fill_method"], inplace=True)
# 設定上升序列和下降序列的名稱和分類
up_seq.name = f"TD_SEQ_UPa" if show_all else f"TD_SEQ_UP"
down_seq.name = f"TD_SEQ_DNa" if show_all else f"TD_SEQ_DN"
up_seq.category = down_seq.category = "momentum"
# 準備要返回的 DataFrame
df = DataFrame({up_seq.name: up_seq, down_seq.name: down_seq})
df.name = "TD_SEQ"
df.category = up_seq.category
return df
# 設定函式文件字串
td_seq.__doc__ = \
"""TD Sequential (TD_SEQ)
Tom DeMark's Sequential indicator attempts to identify a price point where an
uptrend or a downtrend exhausts itself and reverses.
Sources:
https://tradetrekker.wordpress.com/tdsequential/
Calculation:
Compare current close price with 4 days ago price, up to 13 days. For the
consecutive ascending or descending price sequence, display 6th to 9th day
value.
Args:
close (pd.Series): Series of 'close's
asint (bool): If True, fillnas with 0 and change type to int. Default: False
offset (int): How many periods to offset the result. Default: 0
Kwargs:
"""
# 定義函式引數show_all,用於控制展示範圍,預設為True,即展示1到13;如果設定為False,僅展示6到9。
show_all (bool): Show 1 - 13. If set to False, show 6 - 9. Default: True
# 定義函式引數fillna,用於填充缺失值,引數value為填充的數值,預設為空。
fillna (value, optional): pd.DataFrame.fillna(value)
# 返回型別說明:返回的是一個 Pandas DataFrame,其中包含了生成的新特徵。
.\pandas-ta\pandas_ta\momentum\trix.py
# -*- coding: utf-8 -*-
# 從 pandas 庫中匯入 DataFrame 類
from pandas import DataFrame
# 從 pandas_ta 庫中匯入 overlap 模組下的 ema 函式
from pandas_ta.overlap.ema import ema
# 從 pandas_ta 庫中匯入 utils 模組
from pandas_ta.utils import get_drift, get_offset, verify_series
# 定義 Trix 指標函式,用於計算 Trix (TRIX) 指標
def trix(close, length=None, signal=None, scalar=None, drift=None, offset=None, **kwargs):
"""Indicator: Trix (TRIX)"""
# 驗證引數
length = int(length) if length and length > 0 else 30
signal = int(signal) if signal and signal > 0 else 9
scalar = float(scalar) if scalar else 100
close = verify_series(close, max(length, signal))
drift = get_drift(drift)
offset = get_offset(offset)
# 如果 close 為空,則返回空值
if close is None: return
# 計算結果
ema1 = ema(close=close, length=length, **kwargs)
ema2 = ema(close=ema1, length=length, **kwargs)
ema3 = ema(close=ema2, length=length, **kwargs)
trix = scalar * ema3.pct_change(drift)
trix_signal = trix.rolling(signal).mean()
# 偏移
if offset != 0:
trix = trix.shift(offset)
trix_signal = trix_signal.shift(offset)
# 處理填充
if "fillna" in kwargs:
trix.fillna(kwargs["fillna"], inplace=True)
trix_signal.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
trix.fillna(method=kwargs["fill_method"], inplace=True)
trix_signal.fillna(method=kwargs["fill_method"], inplace=True)
# 設定名稱和類別
trix.name = f"TRIX_{length}_{signal}"
trix_signal.name = f"TRIXs_{length}_{signal}"
trix.category = trix_signal.category = "momentum"
# 準備返回的 DataFrame
df = DataFrame({trix.name: trix, trix_signal.name: trix_signal})
df.name = f"TRIX_{length}_{signal}"
df.category = "momentum"
return df
# 設定 trix 函式的文件字串
trix.__doc__ = \
"""Trix (TRIX)
TRIX is a momentum oscillator to identify divergences.
Sources:
https://www.tradingview.com/wiki/TRIX
Calculation:
Default Inputs:
length=18, drift=1
EMA = Exponential Moving Average
ROC = Rate of Change
ema1 = EMA(close, length)
ema2 = EMA(ema1, length)
ema3 = EMA(ema2, length)
TRIX = 100 * ROC(ema3, drift)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 18
signal (int): It's period. Default: 9
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.Series: New feature generated.
"""
.\pandas-ta\pandas_ta\momentum\tsi.py
# -*- coding: utf-8 -*-
# 從 pandas 庫匯入 DataFrame 類
from pandas import DataFrame
# 從 pandas_ta.overlap 模組匯入 ema, ma 函式
from pandas_ta.overlap import ema, ma
# 從 pandas_ta.utils 模組匯入 get_drift, get_offset, verify_series 函式
from pandas_ta.utils import get_drift, get_offset, verify_series
# 定義 True Strength Index (TSI) 指標函式
def tsi(close, fast=None, slow=None, signal=None, scalar=None, mamode=None, drift=None, offset=None, **kwargs):
"""Indicator: True Strength Index (TSI)"""
# 驗證引數有效性
# 如果 fast 引數存在且大於 0,則將其轉換為整數,否則設為預設值 13
fast = int(fast) if fast and fast > 0 else 13
# 如果 slow 引數存在且大於 0,則將其轉換為整數,否則設為預設值 25
slow = int(slow) if slow and slow > 0 else 25
# 如果 signal 引數存在且大於 0,則將其轉換為整數,否則設為預設值 13
signal = int(signal) if signal and signal > 0 else 13
# 如果 close 序列為 None,則返回 None
if close is None: return
# 如果 scalar 存在,則將其轉換為浮點數,否則設為預設值 100
scalar = float(scalar) if scalar else 100
# 獲取漂移值,用於處理偏移
drift = get_drift(drift)
# 獲取偏移量,用於處理偏移
offset = get_offset(offset)
# 如果 mamode 不是字串型別,則將其設為預設值 "ema"
mamode = mamode if isinstance(mamode, str) else "ema"
# 如果 kwargs 中包含 "length" 鍵,則將其移除
if "length" in kwargs: kwargs.pop("length")
# 計算結果
# 計算 close 序列的一階差分
diff = close.diff(drift)
# 計算 slow 期 EMA
slow_ema = ema(close=diff, length=slow, **kwargs)
# 計算 fast 期 EMA
fast_slow_ema = ema(close=slow_ema, length=fast, **kwargs)
# 計算絕對差分
abs_diff = diff.abs()
# 計算 slow 期絕對差分的 EMA
abs_slow_ema = ema(close=abs_diff, length=slow, **kwargs)
# 計算 fast 期絕對差分的 EMA
abs_fast_slow_ema = ema(close=abs_slow_ema, length=fast, **kwargs)
# 計算 TSI
tsi = scalar * fast_slow_ema / abs_fast_slow_ema
# 計算 TSI 的訊號線
tsi_signal = ma(mamode, tsi, length=signal)
# 處理偏移
if offset != 0:
tsi = tsi.shift(offset)
tsi_signal = tsi_signal.shift(offset)
# 處理填充
if "fillna" in kwargs:
tsi.fillna(kwargs["fillna"], inplace=True)
tsi_signal.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
tsi.fillna(method=kwargs["fill_method"], inplace=True)
tsi_signal.fillna(method=kwargs["fill_method"], inplace=True)
# 命名並分類化指標
tsi.name = f"TSI_{fast}_{slow}_{signal}"
tsi_signal.name = f"TSIs_{fast}_{slow}_{signal}"
tsi.category = tsi_signal.category = "momentum"
# 準備返回的 DataFrame
df = DataFrame({tsi.name: tsi, tsi_signal.name: tsi_signal})
df.name = f"TSI_{fast}_{slow}_{signal}"
df.category = "momentum"
return df
# 設定 tsi 函式的文件字串
tsi.__doc__ = \
"""True Strength Index (TSI)
The True Strength Index is a momentum indicator used to identify short-term
swings while in the direction of the trend as well as determining overbought
and oversold conditions.
Sources:
https://www.investopedia.com/terms/t/tsi.asp
Calculation:
Default Inputs:
fast=13, slow=25, signal=13, scalar=100, drift=1
EMA = Exponential Moving Average
diff = close.diff(drift)
slow_ema = EMA(diff, slow)
fast_slow_ema = EMA(slow_ema, slow)
abs_diff_slow_ema = absolute_diff_ema = EMA(ABS(diff), slow)
abema = abs_diff_fast_slow_ema = EMA(abs_diff_slow_ema, fast)
TSI = scalar * fast_slow_ema / abema
Signal = EMA(TSI, signal)
Args:
close (pd.Series): Series of 'close's
fast (int): The short period. Default: 13
slow (int): The long period. Default: 25
signal (int): The signal period. Default: 13
"""
scalar (float): How much to magnify. Default: 100
# 定義一個浮點數變數 scalar,表示放大倍數,預設值為 100
mamode (str): Moving Average of TSI Signal Line.
See ```help(ta.ma)```py. Default: 'ema'
# 定義一個字串變數 mamode,表示 TSI 訊號線的移動平均方式,預設值為 'ema',可檢視 ta.ma 的幫助文件
drift (int): The difference period. Default: 1
# 定義一個整數變數 drift,表示差分週期,預設值為 1
offset (int): How many periods to offset the result. Default: 0
# 定義一個整數變數 offset,表示結果的偏移週期數,預設值為 0
# 函式引數說明部分,kwargs表示可變關鍵字引數
Kwargs:
# fillna引數,用於填充缺失值的值,型別為任意
fillna (value, optional): pd.DataFrame.fillna(value)
# fill_method引數,填充方法的型別
fill_method (value, optional): Type of fill method
# 返回值說明部分,返回一個pandas DataFrame物件,包含tsi和signal兩列
Returns:
# 返回的pandas DataFrame物件,包含tsi和signal兩列資料
pd.DataFrame: tsi, signal.
.\pandas-ta\pandas_ta\momentum\uo.py
# -*- coding: utf-8 -*-
# 匯入 DataFrame 類
from pandas import DataFrame
# 匯入 Imports 類
from pandas_ta import Imports
# 匯入 get_drift 和 get_offset 函式
from pandas_ta.utils import get_drift, get_offset, verify_series
# 定義 Ultimate Oscillator(UO)指標函式
def uo(high, low, close, fast=None, medium=None, slow=None, fast_w=None, medium_w=None, slow_w=None, talib=None, drift=None, offset=None, **kwargs):
"""Indicator: Ultimate Oscillator (UO)"""
# 驗證引數
fast = int(fast) if fast and fast > 0 else 7
fast_w = float(fast_w) if fast_w and fast_w > 0 else 4.0
medium = int(medium) if medium and medium > 0 else 14
medium_w = float(medium_w) if medium_w and medium_w > 0 else 2.0
slow = int(slow) if slow and slow > 0 else 28
slow_w = float(slow_w) if slow_w and slow_w > 0 else 1.0
_length = max(fast, medium, slow)
# 驗證 high、low、close 序列長度
high = verify_series(high, _length)
low = verify_series(low, _length)
close = verify_series(close, _length)
# 獲取漂移和偏移量
drift = get_drift(drift)
offset = get_offset(offset)
# 設定是否使用 talib 模式
mode_tal = bool(talib) if isinstance(talib, bool) else True
# 如果 high、low、close 有任何一個為 None,則返回空
if high is None or low is None or close is None: return
# 計算結果
if Imports["talib"] and mode_tal:
# 使用 talib 計算 UO 指標
from talib import ULTOSC
uo = ULTOSC(high, low, close, fast, medium, slow)
else:
# 否則,使用自定義計算方法
tdf = DataFrame({
"high": high,
"low": low,
f"close_{drift}": close.shift(drift)
})
# 獲取最大最小值
max_h_or_pc = tdf.loc[:, ["high", f"close_{drift}"]].max(axis=1)
min_l_or_pc = tdf.loc[:, ["low", f"close_{drift}"]].min(axis=1)
del tdf
# 計算 buying pressure(bp)和 true range(tr)
bp = close - min_l_or_pc
tr = max_h_or_pc - min_l_or_pc
# 計算 fast、medium、slow 平均值
fast_avg = bp.rolling(fast).sum() / tr.rolling(fast).sum()
medium_avg = bp.rolling(medium).sum() / tr.rolling(medium).sum()
slow_avg = bp.rolling(slow).sum() / tr.rolling(slow).sum()
# 計算總權重和加權平均值
total_weight = fast_w + medium_w + slow_w
weights = (fast_w * fast_avg) + (medium_w * medium_avg) + (slow_w * slow_avg)
uo = 100 * weights / total_weight
# 考慮偏移量
if offset != 0:
uo = uo.shift(offset)
# 處理填充
if "fillna" in kwargs:
uo.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
uo.fillna(method=kwargs["fill_method"], inplace=True)
# 設定指標名稱和分類
uo.name = f"UO_{fast}_{medium}_{slow}"
uo.category = "momentum"
# 返回 Ultimate Oscillator(UO)指標
return uo
# 設定 Ultimate Oscillator(UO)指標的文件字串
uo.__doc__ = \
"""Ultimate Oscillator (UO)
The Ultimate Oscillator is a momentum indicator over three different
periods. It attempts to correct false divergence trading signals.
Sources:
https://www.tradingview.com/wiki/Ultimate_Oscillator_(UO)
Calculation:
Default Inputs:
fast=7, medium=14, slow=28,
fast_w=4.0, medium_w=2.0, slow_w=1.0, drift=1
min_low_or_pc = close.shift(drift).combine(low, min)
max_high_or_pc = close.shift(drift).combine(high, max)
bp = buying pressure = close - min_low_or_pc
tr = true range = max_high_or_pc - min_low_or_pc
fast_avg = SUM(bp, fast) / SUM(tr, fast)
"""
# 計算中等速度的平均值,中等速度報告的總和除以中等速度報告的數量
medium_avg = SUM(bp, medium) / SUM(tr, medium)
# 計算慢速度的平均值,慢速度報告的總和除以慢速度報告的數量
slow_avg = SUM(bp, slow) / SUM(tr, slow)
# 計算所有速度權重的總和
total_weight = fast_w + medium_w + slow_w
# 計算加權平均值,每個速度報告的權重乘以其對應的平均值,然後相加
weights = (fast_w * fast_avg) + (medium_w * medium_avg) + (slow_w * slow_avg)
# 計算不確定性指標(UO),即權重總和乘以100除以所有權重的總和
UO = 100 * weights / total_weight
# 引數說明:
# high (pd.Series): 'high' 資料序列
# low (pd.Series): 'low' 資料序列
# close (pd.Series): 'close' 資料序列
# fast (int): 快速 %K 週期。預設值:7
# medium (int): 慢速 %K 週期。預設值:14
# slow (int): 慢速 %D 週期。預設值:28
# fast_w (float): 快速 %K 週期。預設值:4.0
# medium_w (float): 慢速 %K 週期。預設值:2.0
# slow_w (float): 慢速 %D 週期。預設值:1.0
# talib (bool): 如果安裝了 TA Lib 並且 talib 為 True,則返回 TA Lib 版本。預設值:True
# drift (int): 差異週期。預設值:1
# offset (int): 結果的偏移週期數。預設值:0
# 可選引數:
# fillna (value, optional): pd.DataFrame.fillna(value) 的填充值
# fill_method (value, optional): 填充方法的型別
# 返回值:
# pd.Series: 生成的新特徵序列
.\pandas-ta\pandas_ta\momentum\willr.py
# -*- 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 willr(high, low, close, length=None, talib=None, offset=None, **kwargs):
"""Indicator: William's Percent R (WILLR)"""
# 驗證引數
# 如果 length 存在且大於 0,則將其轉換為整數,否則預設為 14
length = int(length) if length and length > 0 else 14
# 如果 kwargs 中存在 "min_periods",並且其值不為 None,則將其轉換為整數,否則使用 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 = max(length, min_periods)
# 驗證 high、low、close 系列,並設定它們的長度為 _length
high = verify_series(high, _length)
low = verify_series(low, _length)
close = verify_series(close, _length)
# 獲取偏移量
offset = get_offset(offset)
# 確定是否使用 TA-Lib
mode_tal = bool(talib) if isinstance(talib, bool) else True
# 如果 high、low、close 中有任何一個為 None,則返回空
if high is None or low is None or close is None: return
# 計算結果
if Imports["talib"] and mode_tal:
# 如果 TA-Lib 可用且 mode_tal 為 True,則使用 TA-Lib 中的 WILLR 函式計算
from talib import WILLR
willr = WILLR(high, low, close, length)
else:
# 否則,使用自定義方法計算 WILLR
# 計算長度為 length 的最低低點
lowest_low = low.rolling(length, min_periods=min_periods).min()
# 計算長度為 length 的最高高點
highest_high = high.rolling(length, min_periods=min_periods).max()
# 計算 WILLR
willr = 100 * ((close - lowest_low) / (highest_high - lowest_low) - 1)
# 根據偏移量對結果進行偏移
if offset != 0:
willr = willr.shift(offset)
# 處理填充值
if "fillna" in kwargs:
willr.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
willr.fillna(method=kwargs["fill_method"], inplace=True)
# 設定指標名稱和類別
willr.name = f"WILLR_{length}"
willr.category = "momentum"
# 返回計算結果
return willr
# 設定函式文件字串
willr.__doc__ = \
"""William's Percent R (WILLR)
William's Percent R is a momentum oscillator similar to the RSI that
attempts to identify overbought and oversold conditions.
Sources:
https://www.tradingview.com/wiki/Williams_%25R_(%25R)
Calculation:
Default Inputs:
length=20
LL = low.rolling(length).min()
HH = high.rolling(length).max()
WILLR = 100 * ((close - LL) / (HH - LL) - 1)
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
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.
"""