Files
NewQuant/src/indicators/indicators.py

272 lines
8.3 KiB
Python
Raw Normal View History

2025-07-10 15:07:31 +08:00
from typing import List, Union
import numpy as np
import talib
from src.indicators.base_indicators import Indicator
class RSI(Indicator):
"""
相对强弱指数 (RSI) 指标实现使用 TA-Lib 简化计算
"""
2025-07-15 22:45:51 +08:00
def __init__(
self,
window: int = 14,
down_bound: float = None,
up_bound: float = None,
shift_window: int = 0,
):
super().__init__(down_bound, up_bound)
2025-07-10 15:07:31 +08:00
self.window = window
2025-07-15 22:45:51 +08:00
self.shift_window = shift_window
2025-07-10 15:07:31 +08:00
2025-07-15 22:45:51 +08:00
def get_values(
self,
close: np.array,
open: np.array, # 不使用
high: np.array, # 不使用
low: np.array, # 不使用
volume: np.array,
) -> np.array: # 不使用
2025-07-10 15:07:31 +08:00
"""
根据收盘价列表计算RSI值使用 TA-Lib
Args:
close (np.array): 收盘价列表
其他 OHLCV 参数在此指标中不使用
Returns:
np.array: RSI值列表如果数据不足则列表开头为NaN
"""
# 使用 talib.RSI 直接计算
# 注意TA-Lib 会在数据不足时自动填充 NaN
rsi_values = talib.RSI(close, timeperiod=self.window)
# 将 numpy 数组转换为 list 并返回
return rsi_values
2025-07-15 22:45:51 +08:00
2025-07-10 15:07:31 +08:00
def get_name(self):
2025-07-15 22:45:51 +08:00
return f"rsi_{self.window}"
2025-07-10 15:07:31 +08:00
class HistoricalRange(Indicator):
"""
历史波动幅度指标计算过去 N 日的 (最高价 - 最低价) 的简单移动平均
"""
2025-07-15 22:45:51 +08:00
def __init__(
self, down_bound: float = None, up_bound: float = None, shift_window: int = 0
):
super().__init__(down_bound, up_bound)
self.shift_window = shift_window
2025-07-10 15:07:31 +08:00
2025-07-15 22:45:51 +08:00
def get_values(
self,
close: np.array, # 不使用
open: np.array, # 不使用
high: np.array,
low: np.array,
volume: np.array,
) -> np.array: # 不使用
2025-07-10 15:07:31 +08:00
"""
根据最高价和最低价列表计算过去 N 日的 (high - low) 值的简单移动平均
Args:
high (np.array): 最高价列表
low (np.array): 最低价列表
其他 OHLCV 参数在此指标中不使用
Returns:
np.array: 历史波动幅度指标值列表如果数据不足则列表开头为NaN
"""
# if not high or not low or len(high) != len(low):
# print(high, low, len(high), len(low))
# return []
# 计算每日的 (high - low) 范围
daily_ranges = high - low
# 将 numpy 数组转换为 list 并返回
2025-07-15 22:45:51 +08:00
return daily_ranges
def get_name(self):
return f"range_{self.shift_window}"
class DifferencedVolumeIndicator(Indicator):
"""
计算当前交易量与前一交易量的差值
volume[t] - volume[t-1]
用于识别交易量变化的趋势常用于平稳化交易量序列
"""
def __init__(
self, down_bound: float = None, up_bound: float = None, shift_window: int = 0
):
# 差值没有固定上下界,取决于实际交易量
super().__init__(down_bound, up_bound)
self.shift_window = shift_window
def get_values(
self,
close: np.array, # 不使用
open: np.array, # 不使用
high: np.array, # 不使用
low: np.array, # 不使用
volume: np.array,
) -> np.array:
"""
根据交易量计算其差分值
Args:
volume (np.array): 交易量列表
其他 OHLCV 参数在此指标中不使用
Returns:
np.array: 交易量差分值列表第一个值为NaN
"""
if not isinstance(volume, np.ndarray) or len(volume) < 2:
return np.full_like(
volume if isinstance(volume, np.ndarray) else [], np.nan, dtype=float
)
# 计算相邻交易量的差值
# np.diff(volume) 会比原数组少一个元素,前面补 NaN
diff_volume = np.concatenate(([np.nan], np.diff(volume)))
return diff_volume
def get_name(self) -> str:
return f"differenced_volume_{self.shift_window}"
class StochasticOscillator(Indicator):
"""
随机摆动指标 (%K)衡量收盘价在近期价格高低区间内的位置
这是一个平稳的动量摆动指标值域在 [0, 100] 之间
"""
def __init__(
self,
fastk_period: int = 14,
slowk_period: int = 3,
slowd_period: int = 3, # 在此实现中未使用 slowd但保留以符合标准
down_bound: float = None,
up_bound: float = None,
shift_window: int = 0,
):
super().__init__(down_bound, up_bound)
self.fastk_period = fastk_period
self.slowk_period = slowk_period
self.slowd_period = slowd_period
self.shift_window = shift_window
def get_values(
self,
close: np.array,
open: np.array, # 不使用
high: np.array,
low: np.array,
volume: np.array, # 不使用
) -> np.array:
"""
根据最高价最低价和收盘价计算随机摆动指标 %K 的值
Args:
high (np.array): 最高价列表
low (np.array): 最低价列表
close (np.array): 收盘价列表
Returns:
np.array: 慢速 %K 线的值列表
"""
# TA-Lib 的 STOCH 函数返回 slowk 和 slowd 两条线
# 我们通常使用 slowk 作为主要的摆动指标
slowk, _ = talib.STOCH(
high,
low,
close,
fastk_period=self.fastk_period,
slowk_period=self.slowk_period,
slowk_matype=0, # 使用 SMA
slowd_period=self.slowd_period,
slowd_matype=0, # 使用 SMA
)
return slowk
def get_name(self):
return f"stoch_k_{self.fastk_period}_{self.slowk_period}"
class RateOfChange(Indicator):
"""
价格变化率 (ROC)衡量当前价格与 N 期前价格的百分比变化
这是一个平稳的动量指标围绕 0 波动
"""
def __init__(
self,
window: int = 10,
down_bound: float = None,
up_bound: float = None,
shift_window: int = 0,
):
super().__init__(down_bound, up_bound)
self.window = window
self.shift_window = shift_window
def get_values(
self,
close: np.array,
open: np.array, # 不使用
high: np.array, # 不使用
low: np.array, # 不使用
volume: np.array, # 不使用
) -> np.array:
"""
根据收盘价计算 ROC
Args:
close (np.array): 收盘价列表
Returns:
np.array: ROC 值列表
"""
roc_values = talib.ROC(close, timeperiod=self.window)
return roc_values
def get_name(self):
return f"roc_{self.window}"
class NormalizedATR(Indicator):
"""
归一化平均真实波幅 (NATR) ATR / Close * 100
将绝对波动幅度转换为相对波动百分比使其成为一个更平稳的波动率指标
"""
def __init__(
self,
window: int = 14,
down_bound: float = None,
up_bound: float = None,
shift_window: int = 0,
):
super().__init__(down_bound, up_bound)
self.window = window
self.shift_window = shift_window
def get_values(
self,
close: np.array,
open: np.array, # 不使用
high: np.array,
low: np.array,
volume: np.array, # 不使用
) -> np.array:
"""
根据最高价最低价和收盘价计算 NATR
Args:
high (np.array): 最高价列表
low (np.array): 最低价列表
close (np.array): 收盘价列表
Returns:
np.array: NATR 值列表
"""
# 使用 TA-Lib 直接计算 NATR
natr_values = talib.NATR(high, low, close, timeperiod=self.window)
return natr_values
2025-07-10 15:07:31 +08:00
def get_name(self):
2025-07-15 22:45:51 +08:00
return f"natr_{self.window}"