波动系数

This commit is contained in:
zhangkun9038@dingtalk.com 2025-09-28 15:35:31 +08:00
parent 3344f56ee1
commit 586da576b4

View File

@ -33,14 +33,118 @@ class FreqaiPrimer(IStrategy):
# 存储从配置文件加载的默认值
self._trailing_stop_positive_default = 0.004 # 降低默认值以更容易触发跟踪止盈
# 初始化历史波动系数缓存字典,用于存储每个币对的波动系数历史值
# 格式: {pair: [volatility_coefficient1, volatility_coefficient2, ...]}
self._volatility_history = {}
# EMA参数
self._ema_period = 20 # EMA窗口大小
self._max_history_length = 200 # 最大历史记录长度
# 只用于adjust_trade_position方法的波动系数获取
def get_volatility_coefficient(self, pair: str) -> float:
"""
获取币对的波动系数简化版仅用于adjust_trade_position方法
返回固定值1.0假设所有币对波动相当
获取币对的波动系数
- USDT/USDT 波动系数设置为0
- BTC/USDT 波动系数设置为1
- 其他币对
1. 计算当前波动系数 = 该币对波动率 / BTC/USDT波动率
2. 维护最近200个波动系数的历史序列
3. 计算该序列的EMA20值作为最终波动系数
波动系数表示某币对与BTC/USDT相比的波动幅度倍数
- 山寨币的波动系数可能大于3
- 稳定性较高的币对如DOT/USDT波动系数可能小于1
"""
# 检查特殊币对
if pair == 'USDT/USDT':
return 0.0
elif pair == 'BTC/USDT':
return 1.0
try:
# 初始化该币对的历史记录(如果不存在)
if pair not in self._volatility_history:
self._volatility_history[pair] = []
# 1. 计算当前波动系数基于最近的k线数据
current_volatility_coef = self._calculate_current_volatility_coef(pair)
# 2. 将当前波动系数添加到历史记录中
self._volatility_history[pair].append(current_volatility_coef)
# 3. 保持历史记录长度不超过最大限制
if len(self._volatility_history[pair]) > self._max_history_length:
self._volatility_history[pair] = self._volatility_history[pair][-self._max_history_length:]
# 4. 计算EMA20值
if len(self._volatility_history[pair]) >= self._ema_period:
# 使用pandas计算EMA
import pandas as pd
# 创建一个Series对象
vol_series = pd.Series(self._volatility_history[pair])
# 计算EMA20
ema_volatility_coef = vol_series.ewm(span=self._ema_period, adjust=False).mean().iloc[-1]
# 确保EMA值在合理范围内
final_coef = max(0.1, min(5.0, ema_volatility_coef))
self.log_once(f"计算波动系数EMA完成 {pair}: 最终系数={final_coef:.4f} (历史数据点数={len(self._volatility_history[pair])})")
return final_coef
else:
# 如果历史数据不足,返回当前波动系数(或默认值)
# 当历史数据少于EMA周期时使用简单移动平均或直接返回当前值
# 这里选择直接返回当前波动系数,并限制范围
final_coef = max(0.1, min(5.0, current_volatility_coef))
self.log_once(f"计算波动系数EMA完成 {pair}: 最终系数={final_coef:.4f} (历史数据不足,使用当前值)")
return final_coef
except Exception as e:
self.log_once(f"计算波动系数EMA时出错 {pair}: {str(e)}", logger=self.logger.warning)
return 1.0 # 出错时返回默认值1.0
def _calculate_current_volatility_coef(self, pair: str) -> float:
"""
计算当前的波动系数该币对波动率 / BTC/USDT波动率
"""
try:
# 获取当前币对的1小时k线数据
current_pair_df, _ = self.dp.get_analyzed_dataframe(pair, '1h')
# 获取BTC/USDT的1小时k线数据
btc_df, _ = self.dp.get_analyzed_dataframe('BTC/USDT', '1h')
# 确保有足够的数据点
if len(current_pair_df) < 2 or len(btc_df) < 2:
return 1.0 # 如果没有足够数据返回默认值1.0
# 对于数据点少于200个的情况使用所有可用数据
# 对于数据点多于200个的情况使用最近200个数据点
current_data = current_pair_df.iloc[-min(200, len(current_pair_df)):]
btc_data = btc_df.iloc[-min(200, len(btc_df)):]
# 计算当前币对的对数收益率和波动率
current_data['returns'] = current_data['close'].pct_change()
current_volatility = current_data['returns'].std() * 100 # 转换为百分比
# 计算BTC/USDT的对数收益率和波动率
btc_data['returns'] = btc_data['close'].pct_change()
btc_volatility = btc_data['returns'].std() * 100 # 转换为百分比
# 避免除以零的情况
if btc_volatility == 0:
return 1.0
# 计算波动系数:当前币对波动率 / BTC/USDT波动率
volatility_coef = current_volatility / btc_volatility
# 设置合理的上下限,避免极端值影响策略
# 上限设置为5.0(非常高波动的币对)
# 下限设置为0.1(非常稳定的币对)
return max(0.1, min(5.0, volatility_coef))
except Exception as e:
self.log_once(f"计算当前波动系数时出错 {pair}: {str(e)}", logger=self.logger.warning)
return 1.0 # 出错时返回默认值1.0
# 其他辅助方法可以在这里添加
@property