This commit is contained in:
薇薇安 2026-01-17 11:34:19 +08:00
parent ec5cb088a9
commit ff3775eada
5 changed files with 168 additions and 98 deletions

View File

@ -109,20 +109,23 @@ class ConfigManager:
"""获取交易配置字典兼容原有config.py的TRADING_CONFIG""" """获取交易配置字典兼容原有config.py的TRADING_CONFIG"""
return { return {
# 仓位控制 # 仓位控制
'MAX_POSITION_PERCENT': self.get('MAX_POSITION_PERCENT', 0.05), 'MAX_POSITION_PERCENT': self.get('MAX_POSITION_PERCENT', 0.08), # 提高单笔仓位到8%
'MAX_TOTAL_POSITION_PERCENT': self.get('MAX_TOTAL_POSITION_PERCENT', 0.30), 'MAX_TOTAL_POSITION_PERCENT': self.get('MAX_TOTAL_POSITION_PERCENT', 0.40), # 提高总仓位到40%
'MIN_POSITION_PERCENT': self.get('MIN_POSITION_PERCENT', 0.01), 'MIN_POSITION_PERCENT': self.get('MIN_POSITION_PERCENT', 0.02), # 提高最小仓位到2%
'MIN_MARGIN_USDT': self.get('MIN_MARGIN_USDT', 0.5), # 最小保证金要求USDT 'MIN_MARGIN_USDT': self.get('MIN_MARGIN_USDT', 5.0), # 提高最小保证金到5美元
# 涨跌幅阈值 # 涨跌幅阈值
'MIN_CHANGE_PERCENT': self.get('MIN_CHANGE_PERCENT', 2.0), 'MIN_CHANGE_PERCENT': self.get('MIN_CHANGE_PERCENT', 2.0),
'TOP_N_SYMBOLS': self.get('TOP_N_SYMBOLS', 10), 'TOP_N_SYMBOLS': self.get('TOP_N_SYMBOLS', 10),
# 风险控制 # 风险控制
'STOP_LOSS_PERCENT': self.get('STOP_LOSS_PERCENT', 0.10), # 默认10%(更宽松,避免被小幅波动触发) 'STOP_LOSS_PERCENT': self.get('STOP_LOSS_PERCENT', 0.10), # 默认10%
'TAKE_PROFIT_PERCENT': self.get('TAKE_PROFIT_PERCENT', 0.20), # 默认20%(提高盈亏比 'TAKE_PROFIT_PERCENT': self.get('TAKE_PROFIT_PERCENT', 0.30), # 默认30%盈亏比3:1
'MIN_STOP_LOSS_PRICE_PCT': self.get('MIN_STOP_LOSS_PRICE_PCT', 0.02), # 默认2% 'MIN_STOP_LOSS_PRICE_PCT': self.get('MIN_STOP_LOSS_PRICE_PCT', 0.02), # 默认2%
'MIN_TAKE_PROFIT_PRICE_PCT': self.get('MIN_TAKE_PROFIT_PRICE_PCT', 0.03), # 默认3% 'MIN_TAKE_PROFIT_PRICE_PCT': self.get('MIN_TAKE_PROFIT_PRICE_PCT', 0.03), # 默认3%
'USE_ATR_STOP_LOSS': self.get('USE_ATR_STOP_LOSS', True), # 是否使用ATR动态止损
'ATR_STOP_LOSS_MULTIPLIER': self.get('ATR_STOP_LOSS_MULTIPLIER', 1.8), # ATR止损倍数
'ATR_TAKE_PROFIT_MULTIPLIER': self.get('ATR_TAKE_PROFIT_MULTIPLIER', 3.0), # ATR止盈倍数
# 市场扫描1小时主周期 # 市场扫描1小时主周期
'SCAN_INTERVAL': self.get('SCAN_INTERVAL', 3600), # 1小时 'SCAN_INTERVAL': self.get('SCAN_INTERVAL', 3600), # 1小时
@ -141,10 +144,10 @@ class ConfigManager:
'MIN_SIGNAL_STRENGTH': self.get('MIN_SIGNAL_STRENGTH', 5), 'MIN_SIGNAL_STRENGTH': self.get('MIN_SIGNAL_STRENGTH', 5),
'LEVERAGE': self.get('LEVERAGE', 10), 'LEVERAGE': self.get('LEVERAGE', 10),
'USE_DYNAMIC_LEVERAGE': self.get('USE_DYNAMIC_LEVERAGE', True), 'USE_DYNAMIC_LEVERAGE': self.get('USE_DYNAMIC_LEVERAGE', True),
'MAX_LEVERAGE': self.get('MAX_LEVERAGE', 20), 'MAX_LEVERAGE': self.get('MAX_LEVERAGE', 15), # 降低到15更保守配合更大的保证金
'USE_TRAILING_STOP': self.get('USE_TRAILING_STOP', True), 'USE_TRAILING_STOP': self.get('USE_TRAILING_STOP', True),
'TRAILING_STOP_ACTIVATION': self.get('TRAILING_STOP_ACTIVATION', 0.05), # 默认5%(避免过早触发 'TRAILING_STOP_ACTIVATION': self.get('TRAILING_STOP_ACTIVATION', 0.10), # 默认10%(给趋势更多空间
'TRAILING_STOP_PROTECT': self.get('TRAILING_STOP_PROTECT', 0.03), # 默认3%(更合理 'TRAILING_STOP_PROTECT': self.get('TRAILING_STOP_PROTECT', 0.05), # 默认5%(保护更多利润
} }

View File

@ -130,10 +130,10 @@ CREATE TABLE IF NOT EXISTS `trade_recommendations` (
-- 初始化默认配置 -- 初始化默认配置
INSERT INTO `trading_config` (`config_key`, `config_value`, `config_type`, `category`, `description`) VALUES INSERT INTO `trading_config` (`config_key`, `config_value`, `config_type`, `category`, `description`) VALUES
-- 仓位控制 -- 仓位控制
('MAX_POSITION_PERCENT', '0.05', 'number', 'position', '单笔最大仓位:账户余额的5%'), ('MAX_POSITION_PERCENT', '0.08', 'number', 'position', '单笔最大仓位:账户余额的8%(提高收益)'),
('MAX_TOTAL_POSITION_PERCENT', '0.30', 'number', 'position', '总仓位上限:账户余额的30%'), ('MAX_TOTAL_POSITION_PERCENT', '0.40', 'number', 'position', '总仓位上限:账户余额的40%(允许更多持仓)'),
('MIN_POSITION_PERCENT', '0.01', 'number', 'position', '单笔最小仓位:账户余额的1%'), ('MIN_POSITION_PERCENT', '0.02', 'number', 'position', '单笔最小仓位:账户余额的2%(避免过小仓位)'),
('MIN_MARGIN_USDT', '0.5', 'number', 'position', '最小保证金要求:0.5 USDT避免手续费侵蚀收益)'), ('MIN_MARGIN_USDT', '5.0', 'number', 'position', '最小保证金要求:5 USDT提高收益)'),
-- 涨跌幅阈值 -- 涨跌幅阈值
('MIN_CHANGE_PERCENT', '2.0', 'number', 'scan', '最小涨跌幅阈值2%'), ('MIN_CHANGE_PERCENT', '2.0', 'number', 'scan', '最小涨跌幅阈值2%'),
@ -141,10 +141,13 @@ INSERT INTO `trading_config` (`config_key`, `config_value`, `config_type`, `cate
('MAX_SCAN_SYMBOLS', '500', 'number', 'scan', '扫描的最大交易对数量0表示扫描所有建议100-500'), ('MAX_SCAN_SYMBOLS', '500', 'number', 'scan', '扫描的最大交易对数量0表示扫描所有建议100-500'),
-- 风险控制 -- 风险控制
('STOP_LOSS_PERCENT', '0.10', 'number', 'risk', '止损10%(相对于保证金,更宽松避免被小幅波动触发'), ('STOP_LOSS_PERCENT', '0.10', 'number', 'risk', '止损10%(相对于保证金'),
('TAKE_PROFIT_PERCENT', '0.20', 'number', 'risk', '止盈:20%(相对于保证金,提高盈亏比'), ('TAKE_PROFIT_PERCENT', '0.30', 'number', 'risk', '止盈:30%相对于保证金盈亏比3:1'),
('MIN_STOP_LOSS_PRICE_PCT', '0.02', 'number', 'risk', '最小止损价格变动2%(防止止损过紧)'), ('MIN_STOP_LOSS_PRICE_PCT', '0.02', 'number', 'risk', '最小止损价格变动2%(防止止损过紧)'),
('MIN_TAKE_PROFIT_PRICE_PCT', '0.03', 'number', 'risk', '最小止盈价格变动3%(防止止盈过紧)'), ('MIN_TAKE_PROFIT_PRICE_PCT', '0.03', 'number', 'risk', '最小止盈价格变动3%(防止止盈过紧)'),
('USE_ATR_STOP_LOSS', 'true', 'boolean', 'risk', '是否使用ATR动态止损优先于固定百分比'),
('ATR_STOP_LOSS_MULTIPLIER', '1.8', 'number', 'risk', 'ATR止损倍数1.5-2倍ATR默认1.8'),
('ATR_TAKE_PROFIT_MULTIPLIER', '3.0', 'number', 'risk', 'ATR止盈倍数3倍ATR对应3:1盈亏比'),
-- 市场扫描1小时主周期 -- 市场扫描1小时主周期
('SCAN_INTERVAL', '3600', 'number', 'scan', '扫描间隔1小时'), ('SCAN_INTERVAL', '3600', 'number', 'scan', '扫描间隔1小时'),
@ -161,10 +164,10 @@ INSERT INTO `trading_config` (`config_key`, `config_value`, `config_type`, `cate
('MIN_SIGNAL_STRENGTH', '7', 'number', 'strategy', '最小信号强度0-10已提升至7以提高入场质量'), ('MIN_SIGNAL_STRENGTH', '7', 'number', 'strategy', '最小信号强度0-10已提升至7以提高入场质量'),
('LEVERAGE', '10', 'number', 'strategy', '基础杠杆倍数'), ('LEVERAGE', '10', 'number', 'strategy', '基础杠杆倍数'),
('USE_DYNAMIC_LEVERAGE', 'true', 'boolean', 'strategy', '是否启用动态杠杆(根据信号强度调整杠杆倍数)'), ('USE_DYNAMIC_LEVERAGE', 'true', 'boolean', 'strategy', '是否启用动态杠杆(根据信号强度调整杠杆倍数)'),
('MAX_LEVERAGE', '20', 'number', 'strategy', '最大杠杆倍数(动态杠杆上限'), ('MAX_LEVERAGE', '15', 'number', 'strategy', '最大杠杆倍数(动态杠杆上限降低到15更保守'),
('USE_TRAILING_STOP', 'true', 'boolean', 'strategy', '是否使用移动止损'), ('USE_TRAILING_STOP', 'true', 'boolean', 'strategy', '是否使用移动止损'),
('TRAILING_STOP_ACTIVATION', '0.05', 'number', 'strategy', '移动止损激活阈值(盈利5%后激活,避免过早触发'), ('TRAILING_STOP_ACTIVATION', '0.10', 'number', 'strategy', '移动止损激活阈值(盈利10%后激活,给趋势更多空间'),
('TRAILING_STOP_PROTECT', '0.03', 'number', 'strategy', '移动止损保护利润(保护3%利润,更合理)'), ('TRAILING_STOP_PROTECT', '0.05', 'number', 'strategy', '移动止损保护利润(保护5%利润,更合理)'),
-- 持仓同步 -- 持仓同步
('POSITION_SYNC_INTERVAL', '300', 'number', 'scan', '持仓状态同步间隔默认5分钟用于同步币安实际持仓与数据库状态'), ('POSITION_SYNC_INTERVAL', '300', 'number', 'scan', '持仓状态同步间隔默认5分钟用于同步币安实际持仓与数据库状态'),

View File

@ -161,17 +161,20 @@ def _get_trading_config():
return _config_manager.get_trading_config() return _config_manager.get_trading_config()
# 回退到默认配置 # 回退到默认配置
return { return {
'MAX_POSITION_PERCENT': 0.05, 'MAX_POSITION_PERCENT': 0.08, # 提高单笔仓位到8%原来5%),增加收益
'MAX_TOTAL_POSITION_PERCENT': 0.30, 'MAX_TOTAL_POSITION_PERCENT': 0.40, # 提高总仓位到40%原来30%),允许更多持仓
'MIN_POSITION_PERCENT': 0.01, 'MIN_POSITION_PERCENT': 0.02, # 提高最小仓位到2%原来1%),避免过小仓位
'MIN_MARGIN_USDT': 0.5, # 最小保证金要求USDT如果保证金小于此值自动调整到0.5U保证金 'MIN_MARGIN_USDT': 5.0, # 提高最小保证金到5美元原来0.5U),确保收益可观
'MIN_CHANGE_PERCENT': 0.5, # 降低到0.5%以获取更多推荐(推荐系统可以更宽松) 'MIN_CHANGE_PERCENT': 0.5, # 降低到0.5%以获取更多推荐(推荐系统可以更宽松)
'TOP_N_SYMBOLS': 50, # 每次扫描后处理的交易对数量增加到50以获取更多推荐 'TOP_N_SYMBOLS': 50, # 每次扫描后处理的交易对数量增加到50以获取更多推荐
'MAX_SCAN_SYMBOLS': 500, # 扫描的最大交易对数量0表示扫描所有 'MAX_SCAN_SYMBOLS': 500, # 扫描的最大交易对数量0表示扫描所有
'STOP_LOSS_PERCENT': 0.10, # 止损百分比相对于保证金默认10%(更宽松,避免被小幅波动触发) 'STOP_LOSS_PERCENT': 0.10, # 止损百分比相对于保证金默认10%
'TAKE_PROFIT_PERCENT': 0.20, # 止盈百分比相对于保证金默认20%(提高盈亏比 'TAKE_PROFIT_PERCENT': 0.30, # 止盈百分比相对于保证金默认30%盈亏比3:1
'MIN_STOP_LOSS_PRICE_PCT': 0.02, # 最小止损价格变动百分比如0.02表示2%防止止损过紧默认2% 'MIN_STOP_LOSS_PRICE_PCT': 0.02, # 最小止损价格变动百分比如0.02表示2%防止止损过紧默认2%
'MIN_TAKE_PROFIT_PRICE_PCT': 0.03, # 最小止盈价格变动百分比如0.03表示3%防止止盈过紧默认3% 'MIN_TAKE_PROFIT_PRICE_PCT': 0.03, # 最小止盈价格变动百分比如0.03表示3%防止止盈过紧默认3%
'USE_ATR_STOP_LOSS': True, # 是否使用ATR动态止损优先于固定百分比
'ATR_STOP_LOSS_MULTIPLIER': 1.8, # ATR止损倍数1.5-2倍ATR默认1.8
'ATR_TAKE_PROFIT_MULTIPLIER': 3.0, # ATR止盈倍数3倍ATR对应3:1盈亏比
'SCAN_INTERVAL': 3600, 'SCAN_INTERVAL': 3600,
'KLINE_INTERVAL': '1h', 'KLINE_INTERVAL': '1h',
'PRIMARY_INTERVAL': '1h', 'PRIMARY_INTERVAL': '1h',
@ -182,10 +185,10 @@ def _get_trading_config():
'MIN_SIGNAL_STRENGTH': 7, # 提高至7只交易高质量信号简化策略后 'MIN_SIGNAL_STRENGTH': 7, # 提高至7只交易高质量信号简化策略后
'LEVERAGE': 10, # 基础杠杆倍数 'LEVERAGE': 10, # 基础杠杆倍数
'USE_DYNAMIC_LEVERAGE': True, # 是否启用动态杠杆(根据信号强度调整) 'USE_DYNAMIC_LEVERAGE': True, # 是否启用动态杠杆(根据信号强度调整)
'MAX_LEVERAGE': 20, # 最大杠杆倍数(动态杠杆上限 'MAX_LEVERAGE': 15, # 最大杠杆倍数降低到15更保守配合更大的保证金
'USE_TRAILING_STOP': True, 'USE_TRAILING_STOP': True,
'TRAILING_STOP_ACTIVATION': 0.05, # 移动止损激活从1%改为5%(避免过早触发 'TRAILING_STOP_ACTIVATION': 0.10, # 移动止损激活提高到10%盈利10%后激活,给趋势更多空间
'TRAILING_STOP_PROTECT': 0.03, # 保护利润从1%提高到3%更合理) 'TRAILING_STOP_PROTECT': 0.05, # 保护利润提高到5%保护5%利润,更合理)
'POSITION_SYNC_INTERVAL': 300, # 持仓状态同步间隔默认5分钟 'POSITION_SYNC_INTERVAL': 300, # 持仓状态同步间隔默认5分钟
} }

View File

@ -163,6 +163,7 @@ class PositionManager:
atr=atr atr=atr
) )
<<<<<<< Current (Your changes)
# 计算止盈(基于保证金) # 计算止盈(基于保证金)
# 优先使用配置的止盈百分比如果没有配置则使用止损的2倍 # 优先使用配置的止盈百分比如果没有配置则使用止损的2倍
take_profit_pct_margin = self.risk_manager.config.get('TAKE_PROFIT_PERCENT', 0.15) take_profit_pct_margin = self.risk_manager.config.get('TAKE_PROFIT_PERCENT', 0.15)
@ -172,6 +173,18 @@ class PositionManager:
take_profit_price = self.risk_manager.get_take_profit_price( take_profit_price = self.risk_manager.get_take_profit_price(
entry_price, side, quantity, leverage, entry_price, side, quantity, leverage,
take_profit_pct=take_profit_pct_margin take_profit_pct=take_profit_pct_margin
=======
# 计算止盈基于保证金支持ATR动态止盈
# 优先使用配置的止盈百分比如果没有配置则使用止损的3倍盈亏比3:1
take_profit_pct_margin = self.risk_manager.config.get('TAKE_PROFIT_PERCENT', 0.30)
# 如果配置中没有设置止盈则使用止损的3倍作为默认盈亏比3:1
if take_profit_pct_margin is None or take_profit_pct_margin == 0:
take_profit_pct_margin = stop_loss_pct_margin * 3.0
take_profit_price = self.risk_manager.get_take_profit_price(
entry_price, side, quantity, leverage,
take_profit_pct=take_profit_pct_margin,
atr=atr # 传递ATR用于动态止盈
>>>>>>> Incoming (Background Agent changes)
) )
# 下单 # 下单

View File

@ -426,6 +426,28 @@ class RiskManager:
position_value = entry_price * quantity position_value = entry_price * quantity
margin = position_value / leverage if leverage > 0 else position_value margin = position_value / leverage if leverage > 0 else position_value
# 优先使用ATR动态止损如果启用且ATR可用
use_atr_stop = self.config.get('USE_ATR_STOP_LOSS', True)
atr_multiplier = self.config.get('ATR_STOP_LOSS_MULTIPLIER', 1.8)
if use_atr_stop and atr is not None and atr > 0:
# 基于ATR的动态止损
atr_stop_distance = atr * atr_multiplier
if side == 'BUY': # 做多,止损价低于入场价
stop_loss_price_atr = entry_price - atr_stop_distance
else: # 做空,止损价高于入场价
stop_loss_price_atr = entry_price + atr_stop_distance
logger.info(
f"ATR动态止损计算 ({side}): ATR={atr:.4f}, 倍数={atr_multiplier}, "
f"止损距离={atr_stop_distance:.4f}, ATR止损价={stop_loss_price_atr:.4f}"
)
else:
stop_loss_price_atr = None
if use_atr_stop and (atr is None or atr <= 0):
logger.debug(f"ATR不可用使用固定百分比止损")
# 获取止损百分比(相对于保证金) # 获取止损百分比(相对于保证金)
stop_loss_percent = stop_loss_pct or self.config['STOP_LOSS_PERCENT'] stop_loss_percent = stop_loss_pct or self.config['STOP_LOSS_PERCENT']
@ -449,23 +471,27 @@ class RiskManager:
stop_loss_price_price = entry_price * (1 - min_price_change_pct) stop_loss_price_price = entry_price * (1 - min_price_change_pct)
else: else:
stop_loss_price_price = entry_price * (1 + min_price_change_pct) stop_loss_price_price = entry_price * (1 + min_price_change_pct)
# 取更宽松的止损价(对做多取更大的值,对做空取更小的值)
if side == 'BUY':
stop_loss_price = max(stop_loss_price_margin, stop_loss_price_price)
else:
stop_loss_price = min(stop_loss_price_margin, stop_loss_price_price)
logger.info(
f"止损计算 ({side}): 基于保证金={stop_loss_price_margin:.4f}, "
f"基于价格={stop_loss_price_price:.4f}, "
f"最终止损={stop_loss_price:.4f} (取更宽松)"
)
else: else:
# 没有配置最小价格变动,直接使用基于保证金的止损价 stop_loss_price_price = None
stop_loss_price = stop_loss_price_margin
# 如果提供了技术分析数据,可以调整止损价(但不能超过基于保证金的止损范围) # 选择最终的止损价优先ATR其次保证金最后价格百分比取更宽松的
candidate_prices = []
if stop_loss_price_atr is not None:
candidate_prices.append(('ATR', stop_loss_price_atr))
candidate_prices.append(('保证金', stop_loss_price_margin))
if stop_loss_price_price is not None:
candidate_prices.append(('价格百分比', stop_loss_price_price))
# 对做多取最大的值(最宽松),对做空取最小的值(最宽松)
if side == 'BUY':
stop_loss_price = max(p[1] for p in candidate_prices)
selected_method = [p[0] for p in candidate_prices if p[1] == stop_loss_price][0]
else:
stop_loss_price = min(p[1] for p in candidate_prices)
selected_method = [p[0] for p in candidate_prices if p[1] == stop_loss_price][0]
# 如果提供了技术分析数据,计算技术止损(允许更紧的止损,但需要在保证金止损范围内)
technical_stop = None
if klines and len(klines) >= 10: if klines and len(klines) >= 10:
# 计算支撑/阻力位 # 计算支撑/阻力位
low_prices = [float(k[3]) for k in klines[-20:]] # 最近20根K线的最低价 low_prices = [float(k[3]) for k in klines[-20:]] # 最近20根K线的最低价
@ -483,22 +509,14 @@ class RiskManager:
bollinger_stop = bollinger['lower'] * 0.995 # 布林带下轨下方0.5% bollinger_stop = bollinger['lower'] * 0.995 # 布林带下轨下方0.5%
technical_stop = max(technical_stop, bollinger_stop) technical_stop = max(technical_stop, bollinger_stop)
# 使用技术止损,但不能超过基于保证金的止损范围(允许更紧的止损) # 技术止损更紧,但需要确保在保证金止损范围内(不能超过保证金止损)
# 如果技术止损更紧(价格更低),使用技术止损;否则使用基于保证金的止损 if technical_stop < stop_loss_price and technical_stop >= stop_loss_price_margin:
if technical_stop < stop_loss_price: # 技术止损在合理范围内,可以考虑使用
# 技术止损更紧,使用技术止损 candidate_prices.append(('技术分析', technical_stop))
logger.info( logger.debug(
f"动态止损计算 (BUY): 使用技术止损 {technical_stop:.4f} " f"技术止损 (BUY): {technical_stop:.4f} "
f"(基于保证金的止损: {stop_loss_price:.4f}, 止损金额: {stop_loss_amount:.2f} USDT)" f"(在保证金止损范围内)"
) )
return technical_stop
else:
logger.info(
f"动态止损计算 (BUY): 使用基于保证金的止损 {stop_loss_price:.4f} "
f"(技术止损: {technical_stop:.4f}, 止损金额: {stop_loss_amount:.2f} USDT, "
f"止损比例: {stop_loss_percent*100:.1f}% of margin)"
)
return stop_loss_price
else: # 做空,止损放在阻力位上方 else: # 做空,止损放在阻力位上方
# 找到近期波段高点 # 找到近期波段高点
recent_high = max(high_prices) recent_high = max(high_prices)
@ -511,31 +529,32 @@ class RiskManager:
bollinger_stop = bollinger['upper'] * 1.005 # 布林带上轨上方0.5% bollinger_stop = bollinger['upper'] * 1.005 # 布林带上轨上方0.5%
technical_stop = min(technical_stop, bollinger_stop) technical_stop = min(technical_stop, bollinger_stop)
# 使用技术止损,但不能超过基于保证金的止损范围(允许更紧的止损) # 技术止损更紧,但需要确保在保证金止损范围内(不能超过保证金止损)
# 如果技术止损更紧(价格更高),使用技术止损;否则使用基于保证金的止损 if technical_stop > stop_loss_price and technical_stop <= stop_loss_price_margin:
if technical_stop > stop_loss_price: # 技术止损在合理范围内,可以考虑使用
# 技术止损更紧,使用技术止损 candidate_prices.append(('技术分析', technical_stop))
logger.info( logger.debug(
f"动态止损计算 (SELL): 使用技术止损 {technical_stop:.4f} " f"技术止损 (SELL): {technical_stop:.4f} "
f"(基于保证金的止损: {stop_loss_price:.4f}, 止损金额: {stop_loss_amount:.2f} USDT)" f"(在保证金止损范围内)"
) )
return technical_stop
else:
logger.info(
f"动态止损计算 (SELL): 使用基于保证金的止损 {stop_loss_price:.4f} "
f"(技术止损: {technical_stop:.4f}, 止损金额: {stop_loss_amount:.2f} USDT, "
f"止损比例: {stop_loss_percent*100:.1f}% of margin)"
)
return stop_loss_price
# 没有技术分析数据,直接使用基于保证金的止损 # 重新选择最终的止损价(包括技术止损)
if side == 'BUY':
final_stop_loss = max(p[1] for p in candidate_prices)
selected_method = [p[0] for p in candidate_prices if p[1] == final_stop_loss][0]
else:
final_stop_loss = min(p[1] for p in candidate_prices)
selected_method = [p[0] for p in candidate_prices if p[1] == final_stop_loss][0]
logger.info( logger.info(
f"止损计算 ({side}): 入场价={entry_price:.4f}, 数量={quantity:.4f}, " f"最终止损 ({side}): {final_stop_loss:.4f} (使用{selected_method}), "
f"杠杆={leverage}x, 保证金={margin:.4f} USDT, " + (f"ATR={stop_loss_price_atr:.4f}, " if stop_loss_price_atr else "")
f"止损金额={stop_loss_amount:.4f} USDT ({stop_loss_percent*100:.1f}% of margin), " + f"保证金={stop_loss_price_margin:.4f}, "
f"止损价={stop_loss_price:.4f}" + (f"价格={stop_loss_price_price:.4f}, " if stop_loss_price_price else "")
+ (f"技术={technical_stop:.4f}, " if technical_stop else "")
+ f"止损金额={stop_loss_amount:.2f} USDT ({stop_loss_percent*100:.1f}% of margin)"
) )
return stop_loss_price return final_stop_loss
def get_take_profit_price( def get_take_profit_price(
self, self,
@ -543,10 +562,11 @@ class RiskManager:
side: str, side: str,
quantity: float, quantity: float,
leverage: int, leverage: int,
take_profit_pct: Optional[float] = None take_profit_pct: Optional[float] = None,
atr: Optional[float] = None
) -> float: ) -> float:
""" """
计算止盈价格基于保证金的盈亏金额 计算止盈价格基于保证金的盈亏金额支持ATR动态止盈
Args: Args:
entry_price: 入场价格 entry_price: 入场价格
@ -554,6 +574,7 @@ class RiskManager:
quantity: 持仓数量 quantity: 持仓数量
leverage: 杠杆倍数 leverage: 杠杆倍数
take_profit_pct: 止盈百分比相对于保证金如果为None则使用配置值 take_profit_pct: 止盈百分比相对于保证金如果为None则使用配置值
atr: 平均真实波幅用于计算动态止盈可选
Returns: Returns:
止盈价格 止盈价格
@ -562,6 +583,28 @@ class RiskManager:
position_value = entry_price * quantity position_value = entry_price * quantity
margin = position_value / leverage if leverage > 0 else position_value margin = position_value / leverage if leverage > 0 else position_value
# 优先使用ATR动态止盈如果启用且ATR可用
use_atr_stop = self.config.get('USE_ATR_STOP_LOSS', True)
atr_tp_multiplier = self.config.get('ATR_TAKE_PROFIT_MULTIPLIER', 3.0)
if use_atr_stop and atr is not None and atr > 0:
# 基于ATR的动态止盈对应3:1盈亏比
atr_tp_distance = atr * atr_tp_multiplier
if side == 'BUY': # 做多,止盈价高于入场价
take_profit_price_atr = entry_price + atr_tp_distance
else: # 做空,止盈价低于入场价
take_profit_price_atr = entry_price - atr_tp_distance
logger.info(
f"ATR动态止盈计算 ({side}): ATR={atr:.4f}, 倍数={atr_tp_multiplier}, "
f"止盈距离={atr_tp_distance:.4f}, ATR止盈价={take_profit_price_atr:.4f}"
)
else:
take_profit_price_atr = None
if use_atr_stop and (atr is None or atr <= 0):
logger.debug(f"ATR不可用使用固定百分比止盈")
# 获取止盈百分比(相对于保证金) # 获取止盈百分比(相对于保证金)
take_profit_percent = take_profit_pct or self.config['TAKE_PROFIT_PERCENT'] take_profit_percent = take_profit_pct or self.config['TAKE_PROFIT_PERCENT']
@ -585,27 +628,32 @@ class RiskManager:
take_profit_price_price = entry_price * (1 + min_price_change_pct) take_profit_price_price = entry_price * (1 + min_price_change_pct)
else: else:
take_profit_price_price = entry_price * (1 - min_price_change_pct) take_profit_price_price = entry_price * (1 - min_price_change_pct)
# 取更宽松的止盈价(对做多取更大的值,对做空取更小的值)
if side == 'BUY':
take_profit_price = max(take_profit_price_margin, take_profit_price_price)
else:
take_profit_price = min(take_profit_price_margin, take_profit_price_price)
logger.info(
f"止盈计算 ({side}): 基于保证金={take_profit_price_margin:.4f}, "
f"基于价格={take_profit_price_price:.4f}, "
f"最终止盈={take_profit_price:.4f} (取更宽松)"
)
else: else:
# 没有配置最小价格变动,直接使用基于保证金的止盈价 take_profit_price_price = None
take_profit_price = take_profit_price_margin
# 选择最终的止盈价优先ATR其次保证金最后价格百分比取更宽松的
candidate_prices = []
if take_profit_price_atr is not None:
candidate_prices.append(('ATR', take_profit_price_atr))
candidate_prices.append(('保证金', take_profit_price_margin))
if take_profit_price_price is not None:
candidate_prices.append(('价格百分比', take_profit_price_price))
# 对做多取最大的值(更宽松),对做空取最小的值(更宽松)
if side == 'BUY':
take_profit_price = max(p[1] for p in candidate_prices)
selected_method = [p[0] for p in candidate_prices if p[1] == take_profit_price][0]
else:
take_profit_price = min(p[1] for p in candidate_prices)
selected_method = [p[0] for p in candidate_prices if p[1] == take_profit_price][0]
logger.info( logger.info(
f"止盈计算 ({side}): 入场价={entry_price:.4f}, 数量={quantity:.4f}, " f"止盈计算 ({side}): "
f"杠杆={leverage}x, 保证金={margin:.4f} USDT, " + (f"ATR={take_profit_price_atr:.4f}, " if take_profit_price_atr else "")
f"止盈金额={take_profit_amount:.4f} USDT ({take_profit_percent*100:.1f}% of margin), " + f"基于保证金={take_profit_price_margin:.4f}, "
f"止盈价={take_profit_price:.4f}" + (f"基于价格={take_profit_price_price:.4f}, " if take_profit_price_price else "")
+ f"最终止盈={take_profit_price:.4f} (使用{selected_method}, 取更宽松), "
+ f"止盈金额={take_profit_amount:.4f} USDT ({take_profit_percent*100:.1f}% of margin)"
) )
return take_profit_price return take_profit_price