.\pandas-ta\pandas_ta\utils\_signals.py
# -*- coding: utf-8 -*-
# 匯入 DataFrame 和 Series 類
from pandas import DataFrame, Series
# 匯入自定義函式
from ._core import get_offset, verify_series
from ._math import zero
# 定義函式 _above_below,用於比較兩個 Series 物件的大小關係
def _above_below(series_a: Series, series_b: Series, above: bool = True, asint: bool = True, offset: int = None, **kwargs):
# 確保 series_a 和 series_b 是 Series 物件
series_a = verify_series(series_a)
series_b = verify_series(series_b)
offset = get_offset(offset)
# 將 series_a 和 series_b 中的零值替換為 NaN
series_a.apply(zero)
series_b.apply(zero)
# 計算結果
if above:
current = series_a >= series_b
else:
current = series_a <= series_b
if asint:
current = current.astype(int)
# 偏移
if offset != 0:
current = current.shift(offset)
# 設定名稱和類別
current.name = f"{series_a.name}_{'A' if above else 'B'}_{series_b.name}"
current.category = "utility"
return current
# 定義函式 above,用於比較兩個 Series 物件的大小關係,series_a 大於等於 series_b
def above(series_a: Series, series_b: Series, asint: bool = True, offset: int = None, **kwargs):
return _above_below(series_a, series_b, above=True, asint=asint, offset=offset, **kwargs)
# 定義函式 above_value,用於比較 Series 物件和給定值的大小關係,series_a 大於等於 value
def above_value(series_a: Series, value: float, asint: bool = True, offset: int = None, **kwargs):
if not isinstance(value, (int, float, complex)):
print("[X] value is not a number")
return
series_b = Series(value, index=series_a.index, name=f"{value}".replace(".", "_"))
return _above_below(series_a, series_b, above=True, asint=asint, offset=offset, **kwargs)
# 定義函式 below,用於比較兩個 Series 物件的大小關係,series_a 小於等於 series_b
def below(series_a: Series, series_b: Series, asint: bool = True, offset: int = None, **kwargs):
return _above_below(series_a, series_b, above=False, asint=asint, offset=offset, **kwargs)
# 定義函式 below_value,用於比較 Series 物件和給定值的大小關係,series_a 小於等於 value
def below_value(series_a: Series, value: float, asint: bool = True, offset: int = None, **kwargs):
if not isinstance(value, (int, float, complex)):
print("[X] value is not a number")
return
series_b = Series(value, index=series_a.index, name=f"{value}".replace(".", "_"))
return _above_below(series_a, series_b, above=False, asint=asint, offset=offset, **kwargs)
# 定義函式 cross_value,用於判斷 Series 物件和給定值是否交叉,above 為 True 表示交叉在上方
def cross_value(series_a: Series, value: float, above: bool = True, asint: bool = True, offset: int = None, **kwargs):
series_b = Series(value, index=series_a.index, name=f"{value}".replace(".", "_"))
return cross(series_a, series_b, above, asint, offset, **kwargs)
# 定義函式 cross,用於判斷兩個 Series 物件是否交叉,above 為 True 表示交叉在上方
def cross(series_a: Series, series_b: Series, above: bool = True, asint: bool = True, offset: int = None, **kwargs):
series_a = verify_series(series_a)
series_b = verify_series(series_b)
offset = get_offset(offset)
series_a.apply(zero)
series_b.apply(zero)
# 計算結果
current = series_a > series_b # current is above
previous = series_a.shift(1) < series_b.shift(1) # previous is below
# above if both are true, below if both are false
cross = current & previous if above else ~current & ~previous
if asint:
cross = cross.astype(int)
# 偏移
if offset != 0:
cross = cross.shift(offset)
# 設定名稱和類別
# 設定交叉系列的名稱,根據條件選擇不同的字尾
cross.name = f"{series_a.name}_{'XA' if above else 'XB'}_{series_b.name}"
# 設定交叉系列的類別為"utility"
cross.category = "utility"
# 返回交叉系列物件
return cross
# 根據給定的指標、閾值和引數,生成包含交叉訊號的資料框
def signals(indicator, xa, xb, cross_values, xserie, xserie_a, xserie_b, cross_series, offset) -> DataFrame:
# 建立一個空的資料框
df = DataFrame()
# 如果 xa 不為空且為整數或浮點數型別
if xa is not None and isinstance(xa, (int, float)):
# 如果需要計算交叉值
if cross_values:
# 計算指標在閾值 xa 以上交叉的起始點
crossed_above_start = cross_value(indicator, xa, above=True, offset=offset)
# 計算指標在閾值 xa 以上交叉的結束點
crossed_above_end = cross_value(indicator, xa, above=False, offset=offset)
# 將交叉訊號起始點和結束點新增到資料框中
df[crossed_above_start.name] = crossed_above_start
df[crossed_above_end.name] = crossed_above_end
else:
# 計算指標在閾值 xa 以上的訊號
crossed_above = above_value(indicator, xa, offset=offset)
# 將訊號新增到資料框中
df[crossed_above.name] = crossed_above
# 如果 xb 不為空且為整數或浮點數型別
if xb is not None and isinstance(xb, (int, float)):
# 如果需要計算交叉值
if cross_values:
# 計算指標在閾值 xb 以下交叉的起始點
crossed_below_start = cross_value(indicator, xb, above=True, offset=offset)
# 計算指標在閾值 xb 以下交叉的結束點
crossed_below_end = cross_value(indicator, xb, above=False, offset=offset)
# 將交叉訊號起始點和結束點新增到資料框中
df[crossed_below_start.name] = crossed_below_start
df[crossed_below_end.name] = crossed_below_end
else:
# 計算指標在閾值 xb 以下的訊號
crossed_below = below_value(indicator, xb, offset=offset)
# 將訊號新增到資料框中
df[crossed_below.name] = crossed_below
# 如果 xserie_a 為空,則使用預設值 xserie
if xserie_a is None:
xserie_a = xserie
# 如果 xserie_b 為空,則使用預設值 xserie
if xserie_b is None:
xserie_b = xserie
# 如果 xserie_a 不為空且為有效的資料序列
if xserie_a is not None and verify_series(xserie_a):
# 如果需要計算交叉序列
if cross_series:
# 計算指標與 xserie_a 交叉的起始點
cross_serie_above = cross(indicator, xserie_a, above=True, offset=offset)
else:
# 計算指標在 xserie_a 以上的訊號
cross_serie_above = above(indicator, xserie_a, offset=offset)
# 將訊號新增到資料框中
df[cross_serie_above.name] = cross_serie_above
# 如果 xserie_b 不為空且為有效的資料序列
if xserie_b is not None and verify_series(xserie_b):
# 如果需要計算交叉序列
if cross_series:
# 計算指標與 xserie_b 交叉的起始點
cross_serie_below = cross(indicator, xserie_b, above=False, offset=offset)
else:
# 計算指標在 xserie_b 以下的訊號
cross_serie_below = below(indicator, xserie_b, offset=offset)
# 將訊號新增到資料框中
df[cross_serie_below.name] = cross_serie_below
# 返回生成的資料框
return df
.\pandas-ta\pandas_ta\utils\_time.py
# -*- coding: utf-8 -*-
# 從 datetime 模組中匯入 datetime 類
from datetime import datetime
# 從 time 模組中匯入 localtime 和 perf_counter 函式
from time import localtime, perf_counter
# 從 typing 模組中匯入 Tuple 型別
from typing import Tuple
# 從 pandas 模組中匯入 DataFrame 和 Timestamp 類
from pandas import DataFrame, Timestamp
# 從 pandas_ta 模組中匯入 EXCHANGE_TZ 和 RATE 變數
from pandas_ta import EXCHANGE_TZ, RATE
# 定義函式 df_dates,接受一個 DataFrame 和日期元組作為引數,返回過濾後的 DataFrame
def df_dates(df: DataFrame, dates: Tuple[str, list] = None) -> DataFrame:
"""Yields the DataFrame with the given dates"""
# 若日期元組為空,則返回 None
if dates is None: return None
# 如果日期元組不是列表型別,則將其轉換為列表
if not isinstance(dates, list):
dates = [dates]
# 返回過濾後的 DataFrame,只包含日期元組中指定的日期
return df[df.index.isin(dates)]
# 定義函式 df_month_to_date,接受一個 DataFrame 作為引數,返回當月的 DataFrame
def df_month_to_date(df: DataFrame) -> DataFrame:
"""Yields the Month-to-Date (MTD) DataFrame"""
# 獲取當前日期的月初日期,並判斷 DataFrame 的索引是否大於等於該日期
in_mtd = df.index >= Timestamp.now().strftime("%Y-%m-01")
# 如果有資料在當月,則返回當月的 DataFrame
if any(in_mtd): return df[in_mtd]
# 否則返回原始 DataFrame
return df
# 定義函式 df_quarter_to_date,接受一個 DataFrame 作為引數,返回當季的 DataFrame
def df_quarter_to_date(df: DataFrame) -> DataFrame:
"""Yields the Quarter-to-Date (QTD) DataFrame"""
# 獲取當前日期,並遍歷季度開始的月份
now = Timestamp.now()
for m in [1, 4, 7, 10]:
# 如果當前月份小於等於遍歷到的月份
if now.month <= m:
# 獲取季度開始日期,並判斷 DataFrame 的索引是否大於等於該日期
in_qtr = df.index >= datetime(now.year, m, 1).strftime("%Y-%m-01")
# 如果有資料在當季,則返回當季的 DataFrame
if any(in_qtr): return df[in_qtr]
# 否則返回從當前月份開始的 DataFrame
return df[df.index >= now.strftime("%Y-%m-01")]
# 定義函式 df_year_to_date,接受一個 DataFrame 作為引數,返回當年的 DataFrame
def df_year_to_date(df: DataFrame) -> DataFrame:
"""Yields the Year-to-Date (YTD) DataFrame"""
# 獲取當前日期的年初日期,並判斷 DataFrame 的索引是否大於等於該日期
in_ytd = df.index >= Timestamp.now().strftime("%Y-01-01")
# 如果有資料在當年,則返回當年的 DataFrame
if any(in_ytd): return df[in_ytd]
# 否則返回原始 DataFrame
return df
# 定義函式 final_time,接受一個起始時間引數,返回從起始時間到當前時間的耗時
def final_time(stime: float) -> str:
"""Human readable elapsed time. Calculates the final time elasped since
stime and returns a string with microseconds and seconds."""
# 計算當前時間與起始時間的差值
time_diff = perf_counter() - stime
# 返回耗時的字串,包含毫秒和秒
return f"{time_diff * 1000:2.4f} ms ({time_diff:2.4f} s)"
# 定義函式 get_time,接受交易所名稱、是否顯示全資訊和是否返回字串作為引數,返回當前時間及交易所時間資訊
def get_time(exchange: str = "NYSE", full:bool = True, to_string:bool = False) -> Tuple[None, str]:
"""Returns Current Time, Day of the Year and Percentage, and the current
time of the selected Exchange."""
# 預設交易所時區為東部時間(NYSE)
tz = EXCHANGE_TZ["NYSE"]
# 如果傳入的交易所名稱為字串型別
if isinstance(exchange, str):
# 將交易所名稱轉換為大寫
exchange = exchange.upper()
# 獲取對應交易所的時區資訊
tz = EXCHANGE_TZ[exchange]
# 獲取當前時間
today = Timestamp.now()
# 格式化日期字串
date = f"{today.day_name()} {today.month_name()} {today.day}, {today.year}"
# 獲取當前時間在交易所時區的時間
_today = today.timetuple()
exchange_time = f"{(_today.tm_hour + tz) % 24}:{_today.tm_min:02d}:{_today.tm_sec:02d}"
# 如果需要顯示全資訊
if full:
# 獲取本地時間資訊
lt = localtime()
local_ = f"Local: {lt.tm_hour}:{lt.tm_min:02d}:{lt.tm_sec:02d} {lt.tm_zone}"
# 計算當天在一年中的日期和百分比
doy = f"Day {today.dayofyear}/365 ({100 * round(today.dayofyear/365, 2):.2f}%)"
exchange_ = f"{exchange}: {exchange_time}"
# 構建包含完整資訊的字串
s = f"{date}, {exchange_}, {local_}, {doy}"
else:
# 構建簡略資訊的字串
s = f"{date}, {exchange}: {exchange_time}"
# 如果需要返回字串,則返回構建的字串,否則列印字串並返回 None
return s if to_string else print(s)
# 定義函式 total_time,接受一個 DataFrame 和時間間隔型別引數作為輸入,返回 DataFrame 的總時間間隔
def total_time(df: DataFrame, tf: str = "years") -> float:
"""Calculates the total time of a DataFrame. Difference of the Last and
First index. Options: 'months', 'weeks', 'days', 'hours', 'minutes'
and 'seconds'. Default: 'years'.
Useful for annualization."""
# 計算 DataFrame 的總時間間
TimeFrame = {
"years": time_diff.days / RATE["TRADING_DAYS_PER_YEAR"], # 計算時間差對應的年數
"months": time_diff.days / 30.417, # 計算時間差對應的月數
"weeks": time_diff.days / 7, # 計算時間差對應的週數
"days": time_diff.days, # 計算時間差對應的天數
"hours": time_diff.days * 24, # 計算時間差對應的小時數
"minutes": time_diff.total_seconds() / 60, # 計算時間差對應的分鐘數
"seconds": time_diff.total_seconds() # 計算時間差對應的秒數
}
if isinstance(tf, str) and tf in TimeFrame.keys(): # 檢查 tf 是否為字串且在 TimeFrame 字典的鍵中
return TimeFrame[tf] # 返回對應 tf 的時間差
return TimeFrame["years"] # 如果 tf 不在 TimeFrame 字典的鍵中,則返回預設的年數時間差
# 將 DataFrame 的索引轉換為 UTC 時區,或者使用 tz_convert 將索引設定為 UTC 時區
def to_utc(df: DataFrame) -> DataFrame:
# 檢查 DataFrame 是否為空
if not df.empty:
try:
# 嘗試將索引本地化為 UTC 時區
df.index = df.index.tz_localize("UTC")
except TypeError:
# 如果出現 TypeError,則使用 tz_convert 將索引轉換為 UTC 時區
df.index = df.index.tz_convert("UTC")
# 返回處理後的 DataFrame
return df
# 別名
mtd = df_month_to_date
qtd = df_quarter_to_date
ytd = df_year_to_date
.\pandas-ta\pandas_ta\utils\__init__.py
# 設定檔案編碼為UTF-8,確保可以正確處理中文等特殊字元
# 匯入模組中的所有內容,這些模組包括 _candles、_core、_math、_signals、_time、_metrics 和 data
from ._candles import *
from ._core import *
from ._math import *
from ._signals import *
from ._time import *
from ._metrics import *
from .data import *
.\pandas-ta\pandas_ta\volatility\aberration.py
# -*- coding: utf-8 -*-
# from numpy import sqrt as npsqrt # 匯入 numpy 中的 sqrt 函式並重新命名為 npsqrt(已註釋掉)
from pandas import DataFrame # 從 pandas 庫中匯入 DataFrame 類
from .atr import atr # 從當前包中的 atr 模組中匯入 atr 函式
from pandas_ta.overlap import hlc3, sma # 從 pandas_ta.overlap 模組中匯入 hlc3 和 sma 函式
from pandas_ta.utils import get_offset, verify_series # 從 pandas_ta.utils 模組中匯入 get_offset 和 verify_series 函式
def aberration(high, low, close, length=None, atr_length=None, offset=None, **kwargs):
"""Indicator: Aberration (ABER)"""
# Validate arguments
# 確認引數合法性,若引數未指定或非正整數,則使用預設值
length = int(length) if length and length > 0 else 5
atr_length = int(atr_length) if atr_length and atr_length > 0 else 15
_length = max(atr_length, length) # 選擇最大長度作為計算時使用的長度
high = verify_series(high, _length) # 確認 high Series 的合法性和長度
low = verify_series(low, _length) # 確認 low Series 的合法性和長度
close = verify_series(close, _length) # 確認 close Series 的合法性和長度
offset = get_offset(offset) # 獲取偏移量
if high is None or low is None or close is None: return # 如果輸入資料有缺失,則返回空值
# Calculate Result
# 計算結果
atr_ = atr(high=high, low=low, close=close, length=atr_length) # 計算 ATR 指標
jg = hlc3(high=high, low=low, close=close) # 計算 JG(typical price,即三價均價)
zg = sma(jg, length) # 計算 ZG(SMA of JG)
sg = zg + atr_ # 計算 SG(ZG + ATR)
xg = zg - atr_ # 計算 XG(ZG - ATR)
# Offset
# 偏移結果
if offset != 0:
zg = zg.shift(offset) # 對 ZG 進行偏移
sg = sg.shift(offset) # 對 SG 進行偏移
xg = xg.shift(offset) # 對 XG 進行偏移
atr_ = atr_.shift(offset) # 對 ATR 進行偏移
# Handle fills
# 處理填充缺失值
if "fillna" in kwargs:
zg.fillna(kwargs["fillna"], inplace=True) # 使用指定值填充 ZG 中的缺失值
sg.fillna(kwargs["fillna"], inplace=True) # 使用指定值填充 SG 中的缺失值
xg.fillna(kwargs["fillna"], inplace=True) # 使用指定值填充 XG 中的缺失值
atr_.fillna(kwargs["fillna"], inplace=True) # 使用指定值填充 ATR 中的缺失值
if "fill_method" in kwargs:
zg.fillna(method=kwargs["fill_method"], inplace=True) # 使用指定的填充方法填充 ZG 中的缺失值
sg.fillna(method=kwargs["fill_method"], inplace=True) # 使用指定的填充方法填充 SG 中的缺失值
xg.fillna(method=kwargs["fill_method"], inplace=True) # 使用指定的填充方法填充 XG 中的缺失值
atr_.fillna(method=kwargs["fill_method"], inplace=True) # 使用指定的填充方法填充 ATR 中的缺失值
# Name and Categorize it
# 命名和分類
_props = f"_{length}_{atr_length}" # 用於生成屬性名稱的字尾
zg.name = f"ABER_ZG{_props}" # 設定 ZG Series 的名稱
sg.name = f"ABER_SG{_props}" # 設定 SG Series 的名稱
xg.name = f"ABER_XG{_props}" # 設定 XG Series 的名稱
atr_.name = f"ABER_ATR{_props}" # 設定 ATR Series 的名稱
zg.category = sg.category = "volatility" # 設定 ZG 和 SG Series 的分類為波動性
xg.category = atr_.category = zg.category # 設定 XG 和 ATR Series 的分類與 ZG 相同
# Prepare DataFrame to return
# 準備要返回的 DataFrame
data = {zg.name: zg, sg.name: sg, xg.name: xg, atr_.name: atr_} # 構建資料字典
aberdf = DataFrame(data) # 使用資料字典建立 DataFrame
aberdf.name = f"ABER{_props}" # 設定 DataFrame 的名稱
aberdf.category = zg.category # 設定 DataFrame 的分類與 ZG 相同
return aberdf # 返回計算結果的 DataFrame
aberration.__doc__ = \
"""Aberration
A volatility indicator similar to Keltner Channels.
Sources:
Few internet resources on definitive definition.
Request by Github user homily, issue #46
Calculation:
Default Inputs:
length=5, atr_length=15
ATR = Average True Range
SMA = Simple Moving Average
ATR = ATR(length=atr_length)
JG = TP = HLC3(high, low, close)
ZG = SMA(JG, length)
SG = ZG + ATR
XG = ZG - ATR
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): The short period. Default: 5
atr_length (int): The short period. Default: 15
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
""" # 設定 aberration 函式的文件字串
fill_method (value, optional): 填充方法的型別
# 返回一個 pandas DataFrame,包含 zg、sg、xg、atr 列
.\pandas-ta\pandas_ta\volatility\accbands.py
# -*- coding: utf-8 -*-
# 從 pandas 庫中匯入 DataFrame 類
from pandas import DataFrame
# 從 pandas_ta 庫中的 overlap 模組中匯入 ma 函式
from pandas_ta.overlap import ma
# 從 pandas_ta 庫中的 utils 模組中匯入 get_drift, get_offset, non_zero_range, verify_series 函式
from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
# 定義函式 accbands,用於計算加速帶指標
def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, offset=None, **kwargs):
"""Indicator: Acceleration Bands (ACCBANDS)"""
# 驗證引數
# 若 length 存在且大於 0,則將其轉換為整數型別,否則設為 20
length = int(length) if length and length > 0 else 20
# 若 c 存在且大於 0,則將其轉換為浮點數型別,否則設為 4
c = float(c) if c and c > 0 else 4
# 若 mamode 不為字串型別,則設為 "sma"
mamode = mamode if isinstance(mamode, str) else "sma"
# 驗證 high、low、close 系列,使其長度為 length
high = verify_series(high, length)
low = verify_series(low, length)
close = verify_series(close, length)
# 獲取 drift 和 offset
drift = get_drift(drift)
offset = get_offset(offset)
# 若 high、low、close 存在空值,則返回空值
if high is None or low is None or close is None: return
# 計算結果
# 計算 high 和 low 的非零範圍
high_low_range = non_zero_range(high, low)
# 計算 high_low_range 與 (high + low) 的比值
hl_ratio = high_low_range / (high + low)
# 將 hl_ratio 乘以 c
hl_ratio *= c
# 計算下軌線 _lower
_lower = low * (1 - hl_ratio)
# 計算上軌線 _upper
_upper = high * (1 + hl_ratio)
# 計算移動平均值
lower = ma(mamode, _lower, length=length)
mid = ma(mamode, close, length=length)
upper = ma(mamode, _upper, length=length)
# 對結果進行位移
if offset != 0:
lower = lower.shift(offset)
mid = mid.shift(offset)
upper = upper.shift(offset)
# 處理填充
if "fillna" in kwargs:
lower.fillna(kwargs["fillna"], inplace=True)
mid.fillna(kwargs["fillna"], inplace=True)
upper.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
lower.fillna(method=kwargs["fill_method"], inplace=True)
mid.fillna(method=kwargs["fill_method"], inplace=True)
upper.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
lower.name = f"ACCBL_{length}"
mid.name = f"ACCBM_{length}"
upper.name = f"ACCBU_{length}"
mid.category = upper.category = lower.category = "volatility"
# 準備返回的 DataFrame
data = {lower.name: lower, mid.name: mid, upper.name: upper}
accbandsdf = DataFrame(data)
accbandsdf.name = f"ACCBANDS_{length}"
accbandsdf.category = mid.category
return accbandsdf
# 設定函式文件字串
accbands.__doc__ = \
"""Acceleration Bands (ACCBANDS)
Acceleration Bands created by Price Headley plots upper and lower envelope
bands around a simple moving average.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/acceleration-bands-abands/
Calculation:
Default Inputs:
length=10, c=4
EMA = Exponential Moving Average
SMA = Simple Moving Average
HL_RATIO = c * (high - low) / (high + low)
LOW = low * (1 - HL_RATIO)
HIGH = high * (1 + HL_RATIO)
if 'ema':
LOWER = EMA(LOW, length)
MID = EMA(close, length)
UPPER = EMA(HIGH, length)
else:
LOWER = SMA(LOW, length)
MID = SMA(close, length)
UPPER = SMA(HIGH, length)
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
"""
# 表示引數 `length` 是一個整數,代表週期。預設值為 10
length (int): It's period. Default: 10
# 表示引數 `c` 是一個整數,代表乘數。預設值為 4
c (int): Multiplier. Default: 4
# 表示引數 `mamode` 是一個字串,參見 `ta.ma` 的幫助文件。預設值為 'sma'
mamode (str): See ```help(ta.ma)```py. Default: 'sma'
# 表示引數 `drift` 是一個整數,代表差異週期。預設值為 1
drift (int): The difference period. Default: 1
# 表示引數 `offset` 是一個整數,代表結果的偏移週期數。預設值為 0
offset (int): How many periods to offset the result. Default: 0
# 函式引數,用於指定填充缺失值的值,可選引數
fillna (value, optional): pd.DataFrame.fillna(value)
# 函式引數,指定填充方法的型別,可選引數
fill_method (value, optional): Type of fill method
# 返回值,返回一個 DataFrame,包含 lower、mid、upper 列
pd.DataFrame: lower, mid, upper columns.
.\pandas-ta\pandas_ta\volatility\atr.py
# -*- coding: utf-8 -*-
# 匯入 true_range 模組
from .true_range import true_range
# 匯入 Imports 模組
from pandas_ta import Imports
# 匯入 ma 模組
from pandas_ta.overlap import ma
# 匯入 get_drift, get_offset, verify_series 模組
from pandas_ta.utils import get_drift, get_offset, verify_series
# 定義 ATR 函式,計算平均真實範圍
def atr(high, low, close, length=None, mamode=None, talib=None, drift=None, offset=None, **kwargs):
"""Indicator: Average True Range (ATR)"""
# 驗證引數
length = int(length) if length and length > 0 else 14
mamode = mamode.lower() if mamode and isinstance(mamode, str) else "rma"
high = verify_series(high, length)
low = verify_series(low, length)
close = verify_series(close, length)
drift = get_drift(drift)
offset = get_offset(offset)
mode_tal = bool(talib) if isinstance(talib, bool) else True
if high is None or low is None or close is None: return
# 計算結果
if Imports["talib"] and mode_tal:
from talib import ATR
atr = ATR(high, low, close, length)
else:
tr = true_range(high=high, low=low, close=close, drift=drift)
atr = ma(mamode, tr, length=length)
percentage = kwargs.pop("percent", False)
if percentage:
atr *= 100 / close
# 偏移
if offset != 0:
atr = atr.shift(offset)
# 處理填充
if "fillna" in kwargs:
atr.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
atr.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
atr.name = f"ATR{mamode[0]}_{length}{'p' if percentage else ''}"
atr.category = "volatility"
return atr
# 設定 ATR 函式的文件字串
atr.__doc__ = \
"""Average True Range (ATR)
Averge True Range is used to measure volatility, especially volatility caused by
gaps or limit moves.
Sources:
https://www.tradingview.com/wiki/Average_True_Range_(ATR)
Calculation:
Default Inputs:
length=14, drift=1, percent=False
EMA = Exponential Moving Average
SMA = Simple Moving Average
WMA = Weighted Moving Average
RMA = WildeR's Moving Average
TR = True Range
tr = TR(high, low, close, drift)
if 'ema':
ATR = EMA(tr, length)
elif 'sma':
ATR = SMA(tr, length)
elif 'wma':
ATR = WMA(tr, length)
else:
ATR = RMA(tr, length)
if percent:
ATR *= 100 / close
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
mamode (str): See ```help(ta.ma)```py. Default: 'rma'
talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib
version. Default: True
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
percent (bool, optional): Return as percentage. Default: False
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\volatility\bbands.py
# -*- coding: utf-8 -*-
# 匯入所需的庫和模組
from pandas import DataFrame
from pandas_ta import Imports
from pandas_ta.overlap import ma
from pandas_ta.statistics import stdev
from pandas_ta.utils import get_offset, non_zero_range, tal_ma, verify_series
# 定義函式,計算布林帶指標
def bbands(close, length=None, std=None, ddof=0, mamode=None, talib=None, offset=None, **kwargs):
"""Indicator: Bollinger Bands (BBANDS)"""
# 驗證引數
length = int(length) if length and length > 0 else 5
std = float(std) if std and std > 0 else 2.0
mamode = mamode if isinstance(mamode, str) else "sma"
ddof = int(ddof) if ddof >= 0 and ddof < length else 1
close = verify_series(close, length)
offset = get_offset(offset)
mode_tal = bool(talib) if isinstance(talib, bool) else True
if close is None: return
# 計算結果
if Imports["talib"] and mode_tal:
from talib import BBANDS
upper, mid, lower = BBANDS(close, length, std, std, tal_ma(mamode))
else:
standard_deviation = stdev(close=close, length=length, ddof=ddof)
deviations = std * standard_deviation
# deviations = std * standard_deviation.loc[standard_deviation.first_valid_index():,]
mid = ma(mamode, close, length=length, **kwargs)
lower = mid - deviations
upper = mid + deviations
ulr = non_zero_range(upper, lower)
bandwidth = 100 * ulr / mid
percent = non_zero_range(close, lower) / ulr
# 偏移
if offset != 0:
lower = lower.shift(offset)
mid = mid.shift(offset)
upper = upper.shift(offset)
bandwidth = bandwidth.shift(offset)
percent = bandwidth.shift(offset)
# 處理填充
if "fillna" in kwargs:
lower.fillna(kwargs["fillna"], inplace=True)
mid.fillna(kwargs["fillna"], inplace=True)
upper.fillna(kwargs["fillna"], inplace=True)
bandwidth.fillna(kwargs["fillna"], inplace=True)
percent.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
lower.fillna(method=kwargs["fill_method"], inplace=True)
mid.fillna(method=kwargs["fill_method"], inplace=True)
upper.fillna(method=kwargs["fill_method"], inplace=True)
bandwidth.fillna(method=kwargs["fill_method"], inplace=True)
percent.fillna(method=kwargs["fill_method"], inplace=True)
# 命名和分類
lower.name = f"BBL_{length}_{std}"
mid.name = f"BBM_{length}_{std}"
upper.name = f"BBU_{length}_{std}"
bandwidth.name = f"BBB_{length}_{std}"
percent.name = f"BBP_{length}_{std}"
upper.category = lower.category = "volatility"
mid.category = bandwidth.category = upper.category
# 準備返回的 DataFrame
data = {
lower.name: lower, mid.name: mid, upper.name: upper,
bandwidth.name: bandwidth, percent.name: percent
}
bbandsdf = DataFrame(data)
bbandsdf.name = f"BBANDS_{length}_{std}"
bbandsdf.category = mid.category
return bbandsdf
# 設定函式文件字串
bbands.__doc__ = \
"""
Bollinger Bands (BBANDS)
John Bollinger 的一種流行的波動率指標。
Sources:
https://www.tradingview.com/wiki/Bollinger_Bands_(BB)
Calculation:
計算方法:
預設引數:
length=5, std=2, mamode="sma", ddof=0
EMA = 指數移動平均
SMA = 簡單移動平均
STDEV = 標準差
計算標準差 stdev = STDEV(close, length, ddof)
如果使用 EMA:
計算 MID = EMA(close, length)
否則:
計算 MID = SMA(close, length)
LOWER = MID - std * stdev
UPPER = MID + std * stdev
BANDWIDTH = 100 * (UPPER - LOWER) / MID
PERCENT = (close - LOWER) / (UPPER - LOWER)
Args:
close (pd.Series): 'close' 的序列
length (int): 短週期。預設值:5
std (int): 長週期。預設值:2
ddof (int): 使用的自由度。預設值:0
mamode (str): 參見 ```help(ta.ma)```py。預設值:'sma'
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: lower、mid、upper、bandwidth 和 percent 列。
"""
.\pandas-ta\pandas_ta\volatility\donchian.py
# -*- coding: utf-8 -*-
# 從 pandas 庫匯入 DataFrame 類
from pandas import DataFrame
# 從 pandas_ta.utils 模組中匯入 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 定義函式:唐奇安通道(Donchian Channels,DC)
def donchian(high, low, lower_length=None, upper_length=None, offset=None, **kwargs):
"""Indicator: Donchian Channels (DC)"""
# 驗證引數
# 如果 lower_length 存在且大於 0,則將其轉換為整數,否則設為預設值 20
lower_length = int(lower_length) if lower_length and lower_length > 0 else 20
# 如果 upper_length 存在且大於 0,則將其轉換為整數,否則設為預設值 20
upper_length = int(upper_length) if upper_length and upper_length > 0 else 20
# 如果 kwargs 中存在 "lower_min_periods",則將其轉換為整數,否則設為 lower_length 的值
lower_min_periods = int(kwargs["lower_min_periods"]) if "lower_min_periods" in kwargs and kwargs["lower_min_periods"] is not None else lower_length
# 如果 kwargs 中存在 "upper_min_periods",則將其轉換為整數,否則設為 upper_length 的值
upper_min_periods = int(kwargs["upper_min_periods"]) if "upper_min_periods" in kwargs and kwargs["upper_min_periods"] is not None else upper_length
# 計算有效期最大值
_length = max(lower_length, lower_min_periods, upper_length, upper_min_periods)
# 驗證 high 和 low Series
high = verify_series(high, _length)
low = verify_series(low, _length)
# 獲取偏移量
offset = get_offset(offset)
# 如果 high 或 low 為 None,則返回空
if high is None or low is None: return
# 計算結果
# 計算下界,使用滾動視窗計算最小值
lower = low.rolling(lower_length, min_periods=lower_min_periods).min()
# 計算上界,使用滾動視窗計算最大值
upper = high.rolling(upper_length, min_periods=upper_min_periods).max()
# 計算中位數
mid = 0.5 * (lower + upper)
# 填充缺失值
if "fillna" in kwargs:
lower.fillna(kwargs["fillna"], inplace=True)
mid.fillna(kwargs["fillna"], inplace=True)
upper.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
lower.fillna(method=kwargs["fill_method"], inplace=True)
mid.fillna(method=kwargs["fill_method"], inplace=True)
upper.fillna(method=kwargs["fill_method"], inplace=True)
# 偏移結果
if offset != 0:
lower = lower.shift(offset)
mid = mid.shift(offset)
upper = upper.shift(offset)
# 設定名稱和類別
lower.name = f"DCL_{lower_length}_{upper_length}"
mid.name = f"DCM_{lower_length}_{upper_length}"
upper.name = f"DCU_{lower_length}_{upper_length}"
mid.category = upper.category = lower.category = "volatility"
# 準備返回的 DataFrame
data = {lower.name: lower, mid.name: mid, upper.name: upper}
dcdf = DataFrame(data)
dcdf.name = f"DC_{lower_length}_{upper_length}"
dcdf.category = mid.category
return dcdf
# 將函式的文件字串設定為說明唐奇安通道的計算方法和引數含義
donchian.__doc__ = \
"""Donchian Channels (DC)
Donchian Channels are used to measure volatility, similar to
Bollinger Bands and Keltner Channels.
Sources:
https://www.tradingview.com/wiki/Donchian_Channels_(DC)
Calculation:
Default Inputs:
lower_length=upper_length=20
LOWER = low.rolling(lower_length).min()
UPPER = high.rolling(upper_length).max()
MID = 0.5 * (LOWER + UPPER)
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
lower_length (int): The short period. Default: 20
upper_length (int): The short period. Default: 20
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
"""
fill_method (value, optional): Type of fill method
# 填充方法(可選引數):填充方法的型別
# 返回一個 pandas DataFrame 物件,包含 lower、mid 和 upper 列。
.\pandas-ta\pandas_ta\volatility\hwc.py
# -*- coding: utf-8 -*-
# 匯入 numpy 庫中的 sqrt 函式並重新命名為 npSqrt
from numpy import sqrt as npSqrt
# 匯入 pandas 庫中的 DataFrame 和 Series 類
from pandas import DataFrame, Series
# 匯入 pandas_ta 庫中的 get_offset 和 verify_series 函式
from pandas_ta.utils import get_offset, verify_series
# 定義 Holt-Winter Channel 指標函式,接受 close 資料和一系列引數
def hwc(close, na=None, nb=None, nc=None, nd=None, scalar=None, channel_eval=None, offset=None, **kwargs):
"""Indicator: Holt-Winter Channel"""
# 驗證引數
na = float(na) if na and na > 0 else 0.2
nb = float(nb) if nb and nb > 0 else 0.1
nc = float(nc) if nc and nc > 0 else 0.1
nd = float(nd) if nd and nd > 0 else 0.1
scalar = float(scalar) if scalar and scalar > 0 else 1
channel_eval = bool(channel_eval) if channel_eval and channel_eval else False
close = verify_series(close)
offset = get_offset(offset)
# 計算結果
last_a = last_v = last_var = 0
last_f = last_price = last_result = close[0]
lower, result, upper = [], [], []
chan_pct_width, chan_width = [], []
m = close.size
# 遍歷 close 資料
for i in range(m):
# 計算 F、V、A
F = (1.0 - na) * (last_f + last_v + 0.5 * last_a) + na * close[i]
V = (1.0 - nb) * (last_v + last_a) + nb * (F - last_f)
A = (1.0 - nc) * last_a + nc * (V - last_v)
result.append((F + V + 0.5 * A))
# 計算方差和標準差
var = (1.0 - nd) * last_var + nd * (last_price - last_result) * (last_price - last_result)
stddev = npSqrt(last_var)
upper.append(result[i] + scalar * stddev)
lower.append(result[i] - scalar * stddev)
if channel_eval:
# 計算通道寬度和價格位置
chan_width.append(upper[i] - lower[i])
chan_pct_width.append((close[i] - lower[i]) / (upper[i] - lower[i]))
# 更新數值
last_price = close[i]
last_a = A
last_f = F
last_v = V
last_var = var
last_result = result[i]
# 聚合結果
hwc = Series(result, index=close.index)
hwc_upper = Series(upper, index=close.index)
hwc_lower = Series(lower, index=close.index)
if channel_eval:
hwc_width = Series(chan_width, index=close.index)
hwc_pctwidth = Series(chan_pct_width, index=close.index)
# 偏移資料
if offset != 0:
hwc = hwc.shift(offset)
hwc_upper = hwc_upper.shift(offset)
hwc_lower = hwc_lower.shift(offset)
if channel_eval:
hwc_width = hwc_width.shift(offset)
hwc_pctwidth = hwc_pctwidth.shift(offset)
# 處理��充值
if "fillna" in kwargs:
hwc.fillna(kwargs["fillna"], inplace=True)
hwc_upper.fillna(kwargs["fillna"], inplace=True)
hwc_lower.fillna(kwargs["fillna"], inplace=True)
if channel_eval:
hwc_width.fillna(kwargs["fillna"], inplace=True)
hwc_pctwidth.fillna(kwargs["fillna"], inplace=True)
# 檢查是否在引數 kwargs 中包含了 "fill_method" 鍵
if "fill_method" in kwargs:
# 對 hwc DataFrame 中的缺失值進行填充,使用 kwargs 中指定的填充方法,inplace 引數設為 True 表示就地修改
hwc.fillna(method=kwargs["fill_method"], inplace=True)
# 對 hwc_upper DataFrame 中的缺失值進行填充,使用 kwargs 中指定的填充方法,inplace 引數設為 True 表示就地修改
hwc_upper.fillna(method=kwargs["fill_method"], inplace=True)
# 對 hwc_lower DataFrame 中的缺失值進行填充,使用 kwargs 中指定的填充方法,inplace 引數設為 True 表示就地修改
hwc_lower.fillna(method=kwargs["fill_method"], inplace=True)
# 如果需要進行通道評估
if channel_eval:
# 對 hwc_width DataFrame 中的缺失值進行填充,使用 kwargs 中指定的填充方法,inplace 引數設為 True 表示就地修改
hwc_width.fillna(method=kwargs["fill_method"], inplace=True)
# 對 hwc_pctwidth DataFrame 中的缺失值進行填充,使用 kwargs 中指定的填充方法,inplace 引數設為 True 表示就地修改
hwc_pctwidth.fillna(method=kwargs["fill_method"], inplace=True)
# 給 DataFrame 新增名稱和分類
hwc.name = "HWM"
hwc_upper.name = "HWU"
hwc_lower.name = "HWL"
hwc.category = hwc_upper.category = hwc_lower.category = "volatility"
# 如果需要進行通道評估
if channel_eval:
hwc_width.name = "HWW"
hwc_pctwidth.name = "HWPCT"
# 準備要返回的 DataFrame
if channel_eval:
# 構建一個包含各列的字典
data = {hwc.name: hwc, hwc_upper.name: hwc_upper, hwc_lower.name: hwc_lower,
hwc_width.name: hwc_width, hwc_pctwidth.name: hwc_pctwidth}
# 使用字典構建 DataFrame
df = DataFrame(data)
# 設定 DataFrame 的名稱
df.name = "HWC"
# 設定 DataFrame 的分類
df.category = hwc.category
else:
# 構建一個包含各列的字典
data = {hwc.name: hwc, hwc_upper.name: hwc_upper, hwc_lower.name: hwc_lower}
# 使用字典構建 DataFrame
df = DataFrame(data)
# 設定 DataFrame 的名稱
df.name = "HWC"
# 設定 DataFrame 的分類
df.category = hwc.category
# 返回構建好的 DataFrame
return df
# 將 hwc 物件的文件字串設定為指定的內容,用於描述 Holt-Winter 通道指標 HWC(Holt-Winters Channel)
hwc.__doc__ = \
"""HWC (Holt-Winter Channel)
Channel indicator HWC (Holt-Winters Channel) based on HWMA - a three-parameter
moving average calculated by the method of Holt-Winters.
This version has been implemented for Pandas TA by rengel8 based on a
publication for MetaTrader 5 extended by width and percentage price position
against width of channel.
Sources:
https://www.mql5.com/en/code/20857
Calculation:
HWMA[i] = F[i] + V[i] + 0.5 * A[i]
where..
F[i] = (1-na) * (F[i-1] + V[i-1] + 0.5 * A[i-1]) + na * Price[i]
V[i] = (1-nb) * (V[i-1] + A[i-1]) + nb * (F[i] - F[i-1])
A[i] = (1-nc) * A[i-1] + nc * (V[i] - V[i-1])
Top = HWMA + Multiplier * StDt
Bottom = HWMA - Multiplier * StDt
where..
StDt[i] = Sqrt(Var[i-1])
Var[i] = (1-d) * Var[i-1] + nD * (Price[i-1] - HWMA[i-1]) * (Price[i-1] - HWMA[i-1])
Args:
na - parameter of the equation that describes a smoothed series (from 0 to 1)
nb - parameter of the equation to assess the trend (from 0 to 1)
nc - parameter of the equation to assess seasonality (from 0 to 1)
nd - parameter of the channel equation (from 0 to 1)
scaler - multiplier for the width of the channel calculated
channel_eval - boolean to return width and percentage price position against price
close (pd.Series): Series of 'close's
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: HWM (Mid), HWU (Upper), HWL (Lower) columns.
"""