a
This commit is contained in:
parent
cb33556909
commit
c2a78f1f7d
|
|
@ -201,23 +201,31 @@ const StatsDashboard = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从配置获取止损止盈比例(优先使用dashboard返回的配置,其次使用单独加载的配置)
|
// 计算保证金(用于基于保证金的止损止盈)
|
||||||
|
const quantity = parseFloat(trade.quantity || 0)
|
||||||
|
const leverage = parseFloat(trade.leverage || 10)
|
||||||
|
const entryValue = trade.entry_value_usdt !== undefined
|
||||||
|
? parseFloat(trade.entry_value_usdt)
|
||||||
|
: (quantity * entryPrice)
|
||||||
|
const margin = leverage > 0 ? entryValue / leverage : entryValue
|
||||||
|
|
||||||
|
// 从配置获取止损止盈比例(相对于保证金)
|
||||||
const configSource = dashboardData?.trading_config || tradingConfig
|
const configSource = dashboardData?.trading_config || tradingConfig
|
||||||
const stopLossConfig = configSource?.STOP_LOSS_PERCENT
|
const stopLossConfig = configSource?.STOP_LOSS_PERCENT
|
||||||
const takeProfitConfig = configSource?.TAKE_PROFIT_PERCENT
|
const takeProfitConfig = configSource?.TAKE_PROFIT_PERCENT
|
||||||
|
|
||||||
// 配置值是小数形式(0.03表示3%),需要转换为百分比
|
// 配置值是小数形式(0.03表示3%),相对于保证金
|
||||||
let defaultStopLossPercent = 3.0 // 默认3%
|
let stopLossPercentMargin = 0.03 // 默认3%(相对于保证金)
|
||||||
let defaultTakeProfitPercent = 5.0 // 默认5%
|
let takeProfitPercentMargin = 0.05 // 默认5%(相对于保证金)
|
||||||
|
|
||||||
if (stopLossConfig) {
|
if (stopLossConfig) {
|
||||||
const configValue = stopLossConfig.value
|
const configValue = stopLossConfig.value
|
||||||
if (typeof configValue === 'number') {
|
if (typeof configValue === 'number') {
|
||||||
defaultStopLossPercent = configValue * 100
|
stopLossPercentMargin = configValue
|
||||||
} else {
|
} else {
|
||||||
const parsed = parseFloat(configValue)
|
const parsed = parseFloat(configValue)
|
||||||
if (!isNaN(parsed)) {
|
if (!isNaN(parsed)) {
|
||||||
defaultStopLossPercent = parsed * 100
|
stopLossPercentMargin = parsed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -225,32 +233,45 @@ const StatsDashboard = () => {
|
||||||
if (takeProfitConfig) {
|
if (takeProfitConfig) {
|
||||||
const configValue = takeProfitConfig.value
|
const configValue = takeProfitConfig.value
|
||||||
if (typeof configValue === 'number') {
|
if (typeof configValue === 'number') {
|
||||||
defaultTakeProfitPercent = configValue * 100
|
takeProfitPercentMargin = configValue
|
||||||
} else {
|
} else {
|
||||||
const parsed = parseFloat(configValue)
|
const parsed = parseFloat(configValue)
|
||||||
if (!isNaN(parsed)) {
|
if (!isNaN(parsed)) {
|
||||||
defaultTakeProfitPercent = parsed * 100
|
takeProfitPercentMargin = parsed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算止损价和止盈价(基于默认比例)
|
// 计算止损止盈金额(相对于保证金)
|
||||||
|
const stopLossAmount = margin * stopLossPercentMargin
|
||||||
|
const takeProfitAmount = margin * takeProfitPercentMargin
|
||||||
|
|
||||||
|
// 计算止损价和止盈价(基于保证金金额)
|
||||||
|
// 止损金额 = (开仓价 - 止损价) × 数量 或 (止损价 - 开仓价) × 数量
|
||||||
let stopLossPrice = 0
|
let stopLossPrice = 0
|
||||||
let takeProfitPrice = 0
|
let takeProfitPrice = 0
|
||||||
if (side === 'BUY') {
|
if (side === 'BUY') {
|
||||||
stopLossPrice = entryPrice * (1 - defaultStopLossPercent / 100)
|
// 做多:止损价 = 开仓价 - (止损金额 / 数量)
|
||||||
takeProfitPrice = entryPrice * (1 + defaultTakeProfitPercent / 100)
|
stopLossPrice = entryPrice - (stopLossAmount / quantity)
|
||||||
|
// 做多:止盈价 = 开仓价 + (止盈金额 / 数量)
|
||||||
|
takeProfitPrice = entryPrice + (takeProfitAmount / quantity)
|
||||||
} else {
|
} else {
|
||||||
stopLossPrice = entryPrice * (1 + defaultStopLossPercent / 100)
|
// 做空:止损价 = 开仓价 + (止损金额 / 数量)
|
||||||
takeProfitPrice = entryPrice * (1 - defaultTakeProfitPercent / 100)
|
stopLossPrice = entryPrice + (stopLossAmount / quantity)
|
||||||
|
// 做空:止盈价 = 开仓价 - (止盈金额 / 数量)
|
||||||
|
takeProfitPrice = entryPrice - (takeProfitAmount / quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算止损比例和止盈比例(相对于入场价)
|
// 计算止损比例和止盈比例(相对于保证金,用于显示)
|
||||||
const stopLossPercent = side === 'BUY'
|
const stopLossPercent = stopLossPercentMargin * 100 // 相对于保证金
|
||||||
|
const takeProfitPercent = takeProfitPercentMargin * 100 // 相对于保证金
|
||||||
|
|
||||||
|
// 也计算价格百分比(用于参考)
|
||||||
|
const stopLossPercentPrice = side === 'BUY'
|
||||||
? ((entryPrice - stopLossPrice) / entryPrice) * 100
|
? ((entryPrice - stopLossPrice) / entryPrice) * 100
|
||||||
: ((stopLossPrice - entryPrice) / entryPrice) * 100
|
: ((stopLossPrice - entryPrice) / entryPrice) * 100
|
||||||
|
|
||||||
const takeProfitPercent = side === 'BUY'
|
const takeProfitPercentPrice = side === 'BUY'
|
||||||
? ((takeProfitPrice - entryPrice) / entryPrice) * 100
|
? ((takeProfitPrice - entryPrice) / entryPrice) * 100
|
||||||
: ((entryPrice - takeProfitPrice) / entryPrice) * 100
|
: ((entryPrice - takeProfitPrice) / entryPrice) * 100
|
||||||
|
|
||||||
|
|
@ -303,12 +324,16 @@ const StatsDashboard = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="stop-take-info">
|
<div className="stop-take-info">
|
||||||
<div className="stop-loss-info">
|
<div className="stop-loss-info">
|
||||||
止损比例: <span className="negative">-{stopLossPercent.toFixed(2)}%</span>
|
止损: <span className="negative">-{stopLossPercent.toFixed(2)}%</span>
|
||||||
|
<span className="stop-note">(of margin)</span>
|
||||||
<span className="stop-price">(价: {stopLossPrice.toFixed(4)})</span>
|
<span className="stop-price">(价: {stopLossPrice.toFixed(4)})</span>
|
||||||
|
<span className="stop-amount">(金额: -{stopLossAmount.toFixed(2)} USDT)</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="take-profit-info">
|
<div className="take-profit-info">
|
||||||
止盈比例: <span className="positive">+{takeProfitPercent.toFixed(2)}%</span>
|
止盈: <span className="positive">+{takeProfitPercent.toFixed(2)}%</span>
|
||||||
|
<span className="take-note">(of margin)</span>
|
||||||
<span className="take-price">(价: {takeProfitPrice.toFixed(4)})</span>
|
<span className="take-price">(价: {takeProfitPrice.toFixed(4)})</span>
|
||||||
|
<span className="take-amount">(金额: +{takeProfitAmount.toFixed(2)} USDT)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="trade-actions">
|
<div className="trade-actions">
|
||||||
|
|
|
||||||
|
|
@ -145,30 +145,31 @@ class PositionManager:
|
||||||
logger.debug(f"获取K线数据失败,使用固定止损: {e}")
|
logger.debug(f"获取K线数据失败,使用固定止损: {e}")
|
||||||
klines = None
|
klines = None
|
||||||
|
|
||||||
# 使用基于支撑/阻力的动态止损
|
# 使用基于保证金的止损止盈(结合技术分析)
|
||||||
if klines or bollinger or atr:
|
# 计算保证金和仓位价值
|
||||||
stop_loss_price = self.risk_manager.get_stop_loss_price(
|
position_value = entry_price * quantity
|
||||||
entry_price, side,
|
margin = position_value / leverage if leverage > 0 else position_value
|
||||||
klines=klines,
|
|
||||||
bollinger=bollinger,
|
|
||||||
atr=atr
|
|
||||||
)
|
|
||||||
|
|
||||||
# 计算动态止损百分比(用于计算止盈)
|
# 获取止损止盈百分比(相对于保证金)
|
||||||
if side == 'BUY':
|
stop_loss_pct_margin = self.risk_manager.config.get('STOP_LOSS_PERCENT', 0.03)
|
||||||
stop_loss_pct = (entry_price - stop_loss_price) / entry_price
|
take_profit_pct_margin = self.risk_manager.config.get('TAKE_PROFIT_PERCENT', 0.05)
|
||||||
else:
|
|
||||||
stop_loss_pct = (stop_loss_price - entry_price) / entry_price
|
|
||||||
|
|
||||||
# 止盈为止损的2-2.5倍(提高盈亏比)
|
# 计算基于保证金的止损止盈
|
||||||
take_profit_pct = stop_loss_pct * 2.5
|
stop_loss_price = self.risk_manager.get_stop_loss_price(
|
||||||
take_profit_price = self.risk_manager.get_take_profit_price(
|
entry_price, side, quantity, leverage,
|
||||||
entry_price, side, take_profit_pct=take_profit_pct
|
stop_loss_pct=stop_loss_pct_margin,
|
||||||
)
|
klines=klines,
|
||||||
else:
|
bollinger=bollinger,
|
||||||
# 回退到固定止损止盈
|
atr=atr
|
||||||
stop_loss_price = self.risk_manager.get_stop_loss_price(entry_price, side)
|
)
|
||||||
take_profit_price = self.risk_manager.get_take_profit_price(entry_price, side)
|
|
||||||
|
# 计算止盈(基于保证金,为止损的倍数)
|
||||||
|
# 如果止损是保证金的3%,止盈可以是保证金的7.5%(2.5倍)
|
||||||
|
take_profit_pct_margin = stop_loss_pct_margin * 2.5
|
||||||
|
take_profit_price = self.risk_manager.get_take_profit_price(
|
||||||
|
entry_price, side, quantity, leverage,
|
||||||
|
take_profit_pct=take_profit_pct_margin
|
||||||
|
)
|
||||||
|
|
||||||
# 下单
|
# 下单
|
||||||
order = await self.client.place_order(
|
order = await self.client.place_order(
|
||||||
|
|
@ -598,51 +599,70 @@ class PositionManager:
|
||||||
else:
|
else:
|
||||||
current_price = entry_price
|
current_price = entry_price
|
||||||
|
|
||||||
# 计算当前盈亏
|
# 计算当前盈亏(基于保证金)
|
||||||
|
leverage = position_info.get('leverage', 10)
|
||||||
|
position_value = entry_price * quantity
|
||||||
|
margin = position_value / leverage if leverage > 0 else position_value
|
||||||
|
|
||||||
|
# 计算盈亏金额
|
||||||
if position_info['side'] == 'BUY':
|
if position_info['side'] == 'BUY':
|
||||||
pnl_percent = ((current_price - entry_price) / entry_price) * 100
|
pnl_amount = (current_price - entry_price) * quantity
|
||||||
else:
|
else:
|
||||||
pnl_percent = ((entry_price - current_price) / entry_price) * 100
|
pnl_amount = (entry_price - current_price) * quantity
|
||||||
|
|
||||||
# 更新最大盈利
|
# 计算盈亏百分比(相对于保证金,与币安一致)
|
||||||
if pnl_percent > position_info.get('maxProfit', 0):
|
pnl_percent_margin = (pnl_amount / margin * 100) if margin > 0 else 0
|
||||||
position_info['maxProfit'] = pnl_percent
|
|
||||||
|
|
||||||
# 移动止损逻辑(盈利后保护利润)
|
# 也计算价格百分比(用于显示和移动止损)
|
||||||
|
if position_info['side'] == 'BUY':
|
||||||
|
pnl_percent_price = ((current_price - entry_price) / entry_price) * 100
|
||||||
|
else:
|
||||||
|
pnl_percent_price = ((entry_price - current_price) / entry_price) * 100
|
||||||
|
|
||||||
|
# 更新最大盈利(基于保证金)
|
||||||
|
if pnl_percent_margin > position_info.get('maxProfit', 0):
|
||||||
|
position_info['maxProfit'] = pnl_percent_margin
|
||||||
|
|
||||||
|
# 移动止损逻辑(盈利后保护利润,基于保证金)
|
||||||
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', True)
|
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', True)
|
||||||
if use_trailing:
|
if use_trailing:
|
||||||
trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01)
|
trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01) # 相对于保证金
|
||||||
trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01)
|
trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01) # 相对于保证金
|
||||||
|
|
||||||
if not position_info.get('trailingStopActivated', False):
|
if not position_info.get('trailingStopActivated', False):
|
||||||
# 盈利超过阈值后,激活移动止损
|
# 盈利超过阈值后(相对于保证金),激活移动止损
|
||||||
if pnl_percent > trailing_activation * 100:
|
if pnl_percent_margin > trailing_activation * 100:
|
||||||
position_info['trailingStopActivated'] = True
|
position_info['trailingStopActivated'] = True
|
||||||
# 将止损移至成本价(保本)
|
# 将止损移至成本价(保本)
|
||||||
position_info['stopLoss'] = entry_price
|
position_info['stopLoss'] = entry_price
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{symbol} 移动止损激活: 止损移至成本价 {entry_price:.4f} "
|
f"{symbol} 移动止损激活: 止损移至成本价 {entry_price:.4f} "
|
||||||
f"(盈利: {pnl_percent:.2f}%)"
|
f"(盈利: {pnl_percent_margin:.2f}% of margin)"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# 盈利超过2%后,止损移至保护利润位
|
# 盈利超过阈值后,止损移至保护利润位(基于保证金)
|
||||||
if pnl_percent > 2.0:
|
# 计算需要保护的利润金额
|
||||||
if position_info['side'] == 'BUY':
|
protect_amount = margin * trailing_protect
|
||||||
new_stop_loss = entry_price * (1 + trailing_protect)
|
# 计算对应的止损价
|
||||||
if new_stop_loss > position_info['stopLoss']:
|
if position_info['side'] == 'BUY':
|
||||||
position_info['stopLoss'] = new_stop_loss
|
# 保护利润:当前盈亏 - 保护金额 = (止损价 - 开仓价) × 数量
|
||||||
logger.info(
|
# 所以:止损价 = 开仓价 + (当前盈亏 - 保护金额) / 数量
|
||||||
f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
|
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||||
f"(保护{trailing_protect*100:.1f}%利润)"
|
if new_stop_loss > position_info['stopLoss']:
|
||||||
)
|
position_info['stopLoss'] = new_stop_loss
|
||||||
else:
|
logger.info(
|
||||||
new_stop_loss = entry_price * (1 - trailing_protect)
|
f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
|
||||||
if new_stop_loss < position_info['stopLoss']:
|
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||||
position_info['stopLoss'] = new_stop_loss
|
)
|
||||||
logger.info(
|
else:
|
||||||
f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
|
# 做空:止损价 = 开仓价 - (当前盈亏 - 保护金额) / 数量
|
||||||
f"(保护{trailing_protect*100:.1f}%利润)"
|
new_stop_loss = entry_price - (pnl_amount - protect_amount) / quantity
|
||||||
)
|
if new_stop_loss < position_info['stopLoss']:
|
||||||
|
position_info['stopLoss'] = new_stop_loss
|
||||||
|
logger.info(
|
||||||
|
f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
|
||||||
|
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||||
|
)
|
||||||
|
|
||||||
# 检查止损(使用更新后的止损价)
|
# 检查止损(使用更新后的止损价)
|
||||||
stop_loss = position_info.get('stopLoss')
|
stop_loss = position_info.get('stopLoss')
|
||||||
|
|
@ -1064,9 +1084,21 @@ class PositionManager:
|
||||||
ticker = await self.client.get_ticker_24h(symbol)
|
ticker = await self.client.get_ticker_24h(symbol)
|
||||||
current_price = ticker['price'] if ticker else entry_price
|
current_price = ticker['price'] if ticker else entry_price
|
||||||
|
|
||||||
# 计算止损止盈
|
# 计算止损止盈(基于保证金)
|
||||||
stop_loss_price = self.risk_manager.get_stop_loss_price(entry_price, side)
|
leverage = binance_position.get('leverage', 10)
|
||||||
take_profit_price = self.risk_manager.get_take_profit_price(entry_price, side)
|
stop_loss_pct_margin = self.risk_manager.config.get('STOP_LOSS_PERCENT', 0.03)
|
||||||
|
take_profit_pct_margin = self.risk_manager.config.get('TAKE_PROFIT_PERCENT', 0.05)
|
||||||
|
# 止盈为止损的2.5倍
|
||||||
|
take_profit_pct_margin = stop_loss_pct_margin * 2.5
|
||||||
|
|
||||||
|
stop_loss_price = self.risk_manager.get_stop_loss_price(
|
||||||
|
entry_price, side, quantity, leverage,
|
||||||
|
stop_loss_pct=stop_loss_pct_margin
|
||||||
|
)
|
||||||
|
take_profit_price = self.risk_manager.get_take_profit_price(
|
||||||
|
entry_price, side, quantity, leverage,
|
||||||
|
take_profit_pct=take_profit_pct_margin
|
||||||
|
)
|
||||||
|
|
||||||
position_info = {
|
position_info = {
|
||||||
'symbol': symbol,
|
'symbol': symbol,
|
||||||
|
|
@ -1079,7 +1111,7 @@ class PositionManager:
|
||||||
'stopLoss': stop_loss_price,
|
'stopLoss': stop_loss_price,
|
||||||
'takeProfit': take_profit_price,
|
'takeProfit': take_profit_price,
|
||||||
'initialStopLoss': stop_loss_price,
|
'initialStopLoss': stop_loss_price,
|
||||||
'leverage': binance_position.get('leverage', 10),
|
'leverage': leverage,
|
||||||
'entryReason': 'manual_entry',
|
'entryReason': 'manual_entry',
|
||||||
'atr': None,
|
'atr': None,
|
||||||
'maxProfit': 0.0,
|
'maxProfit': 0.0,
|
||||||
|
|
@ -1146,8 +1178,19 @@ class PositionManager:
|
||||||
ticker = await self.client.get_ticker_24h(symbol)
|
ticker = await self.client.get_ticker_24h(symbol)
|
||||||
current_price = ticker['price'] if ticker else entry_price
|
current_price = ticker['price'] if ticker else entry_price
|
||||||
|
|
||||||
stop_loss_price = self.risk_manager.get_stop_loss_price(entry_price, side)
|
# 计算止损止盈(基于保证金)
|
||||||
take_profit_price = self.risk_manager.get_take_profit_price(entry_price, side)
|
leverage = position.get('leverage', 10)
|
||||||
|
stop_loss_pct_margin = self.risk_manager.config.get('STOP_LOSS_PERCENT', 0.03)
|
||||||
|
take_profit_pct_margin = stop_loss_pct_margin * 2.5
|
||||||
|
|
||||||
|
stop_loss_price = self.risk_manager.get_stop_loss_price(
|
||||||
|
entry_price, side, quantity, leverage,
|
||||||
|
stop_loss_pct=stop_loss_pct_margin
|
||||||
|
)
|
||||||
|
take_profit_price = self.risk_manager.get_take_profit_price(
|
||||||
|
entry_price, side, quantity, leverage,
|
||||||
|
take_profit_pct=take_profit_pct_margin
|
||||||
|
)
|
||||||
|
|
||||||
position_info = {
|
position_info = {
|
||||||
'symbol': symbol,
|
'symbol': symbol,
|
||||||
|
|
@ -1160,7 +1203,7 @@ class PositionManager:
|
||||||
'stopLoss': stop_loss_price,
|
'stopLoss': stop_loss_price,
|
||||||
'takeProfit': take_profit_price,
|
'takeProfit': take_profit_price,
|
||||||
'initialStopLoss': stop_loss_price,
|
'initialStopLoss': stop_loss_price,
|
||||||
'leverage': position.get('leverage', 10),
|
'leverage': leverage,
|
||||||
'entryReason': 'manual_entry_temp',
|
'entryReason': 'manual_entry_temp',
|
||||||
'atr': None,
|
'atr': None,
|
||||||
'maxProfit': 0.0,
|
'maxProfit': 0.0,
|
||||||
|
|
@ -1326,51 +1369,70 @@ class PositionManager:
|
||||||
quantity = float(position_info['quantity'])
|
quantity = float(position_info['quantity'])
|
||||||
current_price_float = float(current_price)
|
current_price_float = float(current_price)
|
||||||
|
|
||||||
# 计算当前盈亏
|
# 计算当前盈亏(基于保证金)
|
||||||
|
leverage = position_info.get('leverage', 10)
|
||||||
|
position_value = entry_price * quantity
|
||||||
|
margin = position_value / leverage if leverage > 0 else position_value
|
||||||
|
|
||||||
|
# 计算盈亏金额
|
||||||
if position_info['side'] == 'BUY':
|
if position_info['side'] == 'BUY':
|
||||||
pnl_percent = ((current_price_float - entry_price) / entry_price) * 100
|
pnl_amount = (current_price_float - entry_price) * quantity
|
||||||
else: # SELL
|
else: # SELL
|
||||||
pnl_percent = ((entry_price - current_price_float) / entry_price) * 100
|
pnl_amount = (entry_price - current_price_float) * quantity
|
||||||
|
|
||||||
# 更新最大盈利
|
# 计算盈亏百分比(相对于保证金,与币安一致)
|
||||||
if pnl_percent > position_info.get('maxProfit', 0):
|
pnl_percent_margin = (pnl_amount / margin * 100) if margin > 0 else 0
|
||||||
position_info['maxProfit'] = pnl_percent
|
|
||||||
|
|
||||||
# 移动止损逻辑(盈利后保护利润)
|
# 也计算价格百分比(用于显示)
|
||||||
|
if position_info['side'] == 'BUY':
|
||||||
|
pnl_percent_price = ((current_price_float - entry_price) / entry_price) * 100
|
||||||
|
else: # SELL
|
||||||
|
pnl_percent_price = ((entry_price - current_price_float) / entry_price) * 100
|
||||||
|
|
||||||
|
# 更新最大盈利(基于保证金)
|
||||||
|
if pnl_percent_margin > position_info.get('maxProfit', 0):
|
||||||
|
position_info['maxProfit'] = pnl_percent_margin
|
||||||
|
|
||||||
|
# 移动止损逻辑(盈利后保护利润,基于保证金)
|
||||||
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', True)
|
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', True)
|
||||||
if use_trailing:
|
if use_trailing:
|
||||||
trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01)
|
trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01) # 相对于保证金
|
||||||
trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01)
|
trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01) # 相对于保证金
|
||||||
|
|
||||||
if not position_info.get('trailingStopActivated', False):
|
if not position_info.get('trailingStopActivated', False):
|
||||||
# 盈利超过阈值后,激活移动止损
|
# 盈利超过阈值后(相对于保证金),激活移动止损
|
||||||
if pnl_percent > trailing_activation * 100:
|
if pnl_percent_margin > trailing_activation * 100:
|
||||||
position_info['trailingStopActivated'] = True
|
position_info['trailingStopActivated'] = True
|
||||||
# 将止损移至成本价(保本)
|
# 将止损移至成本价(保本)
|
||||||
position_info['stopLoss'] = entry_price
|
position_info['stopLoss'] = entry_price
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{symbol} [实时监控] 移动止损激活: 止损移至成本价 {entry_price:.4f} "
|
f"{symbol} [实时监控] 移动止损激活: 止损移至成本价 {entry_price:.4f} "
|
||||||
f"(盈利: {pnl_percent:.2f}%)"
|
f"(盈利: {pnl_percent_margin:.2f}% of margin)"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# 盈利超过2%后,止损移至保护利润位
|
# 盈利超过阈值后,止损移至保护利润位(基于保证金)
|
||||||
if pnl_percent > 2.0:
|
# 计算需要保护的利润金额
|
||||||
if position_info['side'] == 'BUY':
|
protect_amount = margin * trailing_protect
|
||||||
new_stop_loss = entry_price * (1 + trailing_protect)
|
# 计算对应的止损价
|
||||||
if new_stop_loss > position_info['stopLoss']:
|
if position_info['side'] == 'BUY':
|
||||||
position_info['stopLoss'] = new_stop_loss
|
# 保护利润:当前盈亏 - 保护金额 = (止损价 - 开仓价) × 数量
|
||||||
logger.info(
|
# 所以:止损价 = 开仓价 + (当前盈亏 - 保护金额) / 数量
|
||||||
f"{symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
|
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||||
f"(保护{trailing_protect*100:.1f}%利润)"
|
if new_stop_loss > position_info['stopLoss']:
|
||||||
)
|
position_info['stopLoss'] = new_stop_loss
|
||||||
else: # SELL
|
logger.info(
|
||||||
new_stop_loss = entry_price * (1 - trailing_protect)
|
f"{symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
|
||||||
if new_stop_loss < position_info['stopLoss']:
|
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||||
position_info['stopLoss'] = new_stop_loss
|
)
|
||||||
logger.info(
|
else: # SELL
|
||||||
f"{symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
|
# 做空:止损价 = 开仓价 - (当前盈亏 - 保护金额) / 数量
|
||||||
f"(保护{trailing_protect*100:.1f}%利润)"
|
new_stop_loss = entry_price - (pnl_amount - protect_amount) / quantity
|
||||||
)
|
if new_stop_loss < position_info['stopLoss']:
|
||||||
|
position_info['stopLoss'] = new_stop_loss
|
||||||
|
logger.info(
|
||||||
|
f"{symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
|
||||||
|
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||||
|
)
|
||||||
|
|
||||||
# 检查止损
|
# 检查止损
|
||||||
stop_loss = position_info['stopLoss']
|
stop_loss = position_info['stopLoss']
|
||||||
|
|
|
||||||
|
|
@ -399,26 +399,48 @@ class RiskManager:
|
||||||
self,
|
self,
|
||||||
entry_price: float,
|
entry_price: float,
|
||||||
side: str,
|
side: str,
|
||||||
|
quantity: float,
|
||||||
|
leverage: int,
|
||||||
stop_loss_pct: Optional[float] = None,
|
stop_loss_pct: Optional[float] = None,
|
||||||
klines: Optional[List] = None,
|
klines: Optional[List] = None,
|
||||||
bollinger: Optional[Dict] = None,
|
bollinger: Optional[Dict] = None,
|
||||||
atr: Optional[float] = None
|
atr: Optional[float] = None
|
||||||
) -> float:
|
) -> float:
|
||||||
"""
|
"""
|
||||||
计算止损价格(基于支撑/阻力的动态止损)
|
计算止损价格(基于保证金的盈亏金额)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
entry_price: 入场价格
|
entry_price: 入场价格
|
||||||
side: 方向 'BUY' 或 'SELL'
|
side: 方向 'BUY' 或 'SELL'
|
||||||
stop_loss_pct: 止损百分比,如果为None则使用配置值
|
quantity: 持仓数量
|
||||||
klines: K线数据,用于计算支撑/阻力位
|
leverage: 杠杆倍数
|
||||||
bollinger: 布林带数据,用于计算动态止损
|
stop_loss_pct: 止损百分比(相对于保证金),如果为None则使用配置值
|
||||||
atr: 平均真实波幅,用于计算动态止损
|
klines: K线数据,用于计算支撑/阻力位(作为辅助参考)
|
||||||
|
bollinger: 布林带数据,用于计算动态止损(作为辅助参考)
|
||||||
|
atr: 平均真实波幅,用于计算动态止损(作为辅助参考)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
止损价格
|
止损价格
|
||||||
"""
|
"""
|
||||||
# 优先使用基于技术结构的动态止损
|
# 计算保证金和仓位价值
|
||||||
|
position_value = entry_price * quantity
|
||||||
|
margin = position_value / leverage if leverage > 0 else position_value
|
||||||
|
|
||||||
|
# 获取止损百分比(相对于保证金)
|
||||||
|
stop_loss_percent = stop_loss_pct or self.config['STOP_LOSS_PERCENT']
|
||||||
|
|
||||||
|
# 计算止损金额(相对于保证金)
|
||||||
|
stop_loss_amount = margin * stop_loss_percent
|
||||||
|
|
||||||
|
# 计算止损价(基于止损金额)
|
||||||
|
# 止损金额 = (开仓价 - 止损价) × 数量
|
||||||
|
# 所以:止损价 = 开仓价 - (止损金额 / 数量)
|
||||||
|
if side == 'BUY': # 做多,止损价低于入场价
|
||||||
|
stop_loss_price = entry_price - (stop_loss_amount / quantity)
|
||||||
|
else: # 做空,止损价高于入场价
|
||||||
|
stop_loss_price = entry_price + (stop_loss_amount / quantity)
|
||||||
|
|
||||||
|
# 如果提供了技术分析数据,可以调整止损价(但不能超过基于保证金的止损范围)
|
||||||
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线的最低价
|
||||||
|
|
@ -427,85 +449,115 @@ class RiskManager:
|
||||||
if side == 'BUY': # 做多,止损放在支撑位下方
|
if side == 'BUY': # 做多,止损放在支撑位下方
|
||||||
# 找到近期波段低点
|
# 找到近期波段低点
|
||||||
recent_low = min(low_prices)
|
recent_low = min(low_prices)
|
||||||
# 止损放在低点下方0.5-1%
|
# 止损放在低点下方0.5%
|
||||||
buffer = entry_price * 0.005 # 0.5%缓冲
|
buffer = entry_price * 0.005 # 0.5%缓冲
|
||||||
dynamic_stop = recent_low - buffer
|
technical_stop = recent_low - buffer
|
||||||
|
|
||||||
# 如果布林带可用,也可以考虑布林带下轨
|
# 如果布林带可用,也可以考虑布林带下轨
|
||||||
if bollinger and bollinger.get('lower'):
|
if bollinger and bollinger.get('lower'):
|
||||||
bollinger_stop = bollinger['lower'] * 0.995 # 布林带下轨下方0.5%
|
bollinger_stop = bollinger['lower'] * 0.995 # 布林带下轨下方0.5%
|
||||||
dynamic_stop = max(dynamic_stop, bollinger_stop)
|
technical_stop = max(technical_stop, bollinger_stop)
|
||||||
|
|
||||||
# 确保止损不超过固定止损范围(1%-5%)
|
# 使用技术止损,但不能超过基于保证金的止损范围(允许更紧的止损)
|
||||||
fixed_stop_pct = stop_loss_pct or self.config['STOP_LOSS_PERCENT']
|
# 如果技术止损更紧(价格更低),使用技术止损;否则使用基于保证金的止损
|
||||||
max_stop = entry_price * (1 - 0.01) # 最多1%止损
|
if technical_stop < stop_loss_price:
|
||||||
min_stop = entry_price * (1 - 0.05) # 最少5%止损(极端情况)
|
# 技术止损更紧,使用技术止损
|
||||||
|
logger.info(
|
||||||
dynamic_stop = max(min_stop, min(max_stop, dynamic_stop))
|
f"动态止损计算 (BUY): 使用技术止损 {technical_stop:.4f} "
|
||||||
|
f"(基于保证金的止损: {stop_loss_price:.4f}, 止损金额: {stop_loss_amount:.2f} USDT)"
|
||||||
logger.info(
|
)
|
||||||
f"动态止损计算 (BUY): 入场价={entry_price:.4f}, "
|
return technical_stop
|
||||||
f"近期低点={recent_low:.4f}, 动态止损={dynamic_stop:.4f}, "
|
else:
|
||||||
f"止损比例={((entry_price - dynamic_stop) / entry_price * 100):.2f}%"
|
logger.info(
|
||||||
)
|
f"动态止损计算 (BUY): 使用基于保证金的止损 {stop_loss_price:.4f} "
|
||||||
return dynamic_stop
|
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)
|
||||||
# 止损放在高点上方0.5-1%
|
# 止损放在高点上方0.5%
|
||||||
buffer = entry_price * 0.005 # 0.5%缓冲
|
buffer = entry_price * 0.005 # 0.5%缓冲
|
||||||
dynamic_stop = recent_high + buffer
|
technical_stop = recent_high + buffer
|
||||||
|
|
||||||
# 如果布林带可用,也可以考虑布林带上轨
|
# 如果布林带可用,也可以考虑布林带上轨
|
||||||
if bollinger and bollinger.get('upper'):
|
if bollinger and bollinger.get('upper'):
|
||||||
bollinger_stop = bollinger['upper'] * 1.005 # 布林带上轨上方0.5%
|
bollinger_stop = bollinger['upper'] * 1.005 # 布林带上轨上方0.5%
|
||||||
dynamic_stop = min(dynamic_stop, bollinger_stop)
|
technical_stop = min(technical_stop, bollinger_stop)
|
||||||
|
|
||||||
# 确保止损不超过固定止损范围(1%-5%)
|
# 使用技术止损,但不能超过基于保证金的止损范围(允许更紧的止损)
|
||||||
fixed_stop_pct = stop_loss_pct or self.config['STOP_LOSS_PERCENT']
|
# 如果技术止损更紧(价格更高),使用技术止损;否则使用基于保证金的止损
|
||||||
min_stop = entry_price * (1 + 0.01) # 最少1%止损
|
if technical_stop > stop_loss_price:
|
||||||
max_stop = entry_price * (1 + 0.05) # 最多5%止损(极端情况)
|
# 技术止损更紧,使用技术止损
|
||||||
|
logger.info(
|
||||||
|
f"动态止损计算 (SELL): 使用技术止损 {technical_stop:.4f} "
|
||||||
|
f"(基于保证金的止损: {stop_loss_price:.4f}, 止损金额: {stop_loss_amount:.2f} USDT)"
|
||||||
|
)
|
||||||
|
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
|
||||||
|
|
||||||
dynamic_stop = min(max_stop, max(min_stop, dynamic_stop))
|
# 没有技术分析数据,直接使用基于保证金的止损
|
||||||
|
logger.info(
|
||||||
logger.info(
|
f"止损计算 ({side}): 入场价={entry_price:.4f}, 数量={quantity:.4f}, "
|
||||||
f"动态止损计算 (SELL): 入场价={entry_price:.4f}, "
|
f"杠杆={leverage}x, 保证金={margin:.4f} USDT, "
|
||||||
f"近期高点={recent_high:.4f}, 动态止损={dynamic_stop:.4f}, "
|
f"止损金额={stop_loss_amount:.4f} USDT ({stop_loss_percent*100:.1f}% of margin), "
|
||||||
f"止损比例={((dynamic_stop - entry_price) / entry_price * 100):.2f}%"
|
f"止损价={stop_loss_price:.4f}"
|
||||||
)
|
)
|
||||||
return dynamic_stop
|
return stop_loss_price
|
||||||
|
|
||||||
# 回退到固定百分比止损
|
|
||||||
stop_loss_percent = stop_loss_pct or self.config['STOP_LOSS_PERCENT']
|
|
||||||
|
|
||||||
if side == 'BUY': # 做多,止损价低于入场价
|
|
||||||
return entry_price * (1 - stop_loss_percent)
|
|
||||||
else: # 做空,止损价高于入场价
|
|
||||||
return entry_price * (1 + stop_loss_percent)
|
|
||||||
|
|
||||||
def get_take_profit_price(
|
def get_take_profit_price(
|
||||||
self,
|
self,
|
||||||
entry_price: float,
|
entry_price: float,
|
||||||
side: str,
|
side: str,
|
||||||
|
quantity: float,
|
||||||
|
leverage: int,
|
||||||
take_profit_pct: Optional[float] = None
|
take_profit_pct: Optional[float] = None
|
||||||
) -> float:
|
) -> float:
|
||||||
"""
|
"""
|
||||||
计算止盈价格
|
计算止盈价格(基于保证金的盈亏金额)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
entry_price: 入场价格
|
entry_price: 入场价格
|
||||||
side: 方向 'BUY' 或 'SELL'
|
side: 方向 'BUY' 或 'SELL'
|
||||||
take_profit_pct: 止盈百分比,如果为None则使用配置值
|
quantity: 持仓数量
|
||||||
|
leverage: 杠杆倍数
|
||||||
|
take_profit_pct: 止盈百分比(相对于保证金),如果为None则使用配置值
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
止盈价格
|
止盈价格
|
||||||
"""
|
"""
|
||||||
|
# 计算保证金和仓位价值
|
||||||
|
position_value = entry_price * quantity
|
||||||
|
margin = position_value / leverage if leverage > 0 else position_value
|
||||||
|
|
||||||
|
# 获取止盈百分比(相对于保证金)
|
||||||
take_profit_percent = take_profit_pct or self.config['TAKE_PROFIT_PERCENT']
|
take_profit_percent = take_profit_pct or self.config['TAKE_PROFIT_PERCENT']
|
||||||
|
|
||||||
|
# 计算止盈金额(相对于保证金)
|
||||||
|
take_profit_amount = margin * take_profit_percent
|
||||||
|
|
||||||
|
# 计算止盈价(基于止盈金额)
|
||||||
|
# 止盈金额 = (止盈价 - 开仓价) × 数量
|
||||||
|
# 所以:止盈价 = 开仓价 + (止盈金额 / 数量)
|
||||||
if side == 'BUY': # 做多,止盈价高于入场价
|
if side == 'BUY': # 做多,止盈价高于入场价
|
||||||
return entry_price * (1 + take_profit_percent)
|
take_profit_price = entry_price + (take_profit_amount / quantity)
|
||||||
else: # 做空,止盈价低于入场价
|
else: # 做空,止盈价低于入场价
|
||||||
return entry_price * (1 - take_profit_percent)
|
take_profit_price = entry_price - (take_profit_amount / quantity)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"止盈计算 ({side}): 入场价={entry_price:.4f}, 数量={quantity:.4f}, "
|
||||||
|
f"杠杆={leverage}x, 保证金={margin:.4f} USDT, "
|
||||||
|
f"止盈金额={take_profit_amount:.4f} USDT ({take_profit_percent*100:.1f}% of margin), "
|
||||||
|
f"止盈价={take_profit_price:.4f}"
|
||||||
|
)
|
||||||
|
return take_profit_price
|
||||||
|
|
||||||
async def calculate_dynamic_leverage(self, signal_strength: int, symbol: str = None) -> int:
|
async def calculate_dynamic_leverage(self, signal_strength: int, symbol: str = None) -> int:
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -358,32 +358,54 @@ class TradeRecommender:
|
||||||
current_price = symbol_info['price']
|
current_price = symbol_info['price']
|
||||||
direction = trade_signal['direction']
|
direction = trade_signal['direction']
|
||||||
|
|
||||||
# 计算建议的止损止盈
|
# 计算建议的止损止盈(基于保证金)
|
||||||
entry_price = current_price
|
entry_price = current_price
|
||||||
|
|
||||||
|
# 估算仓位数量和杠杆(用于计算止损止盈)
|
||||||
|
# 使用建议的仓位比例和账户余额来估算
|
||||||
|
account_balance = symbol_info.get('account_balance', 1000)
|
||||||
|
suggested_position_pct = symbol_info.get('suggested_position_pct', 0.05)
|
||||||
|
leverage = config.TRADING_CONFIG.get('LEVERAGE', 10)
|
||||||
|
|
||||||
|
# 估算仓位价值
|
||||||
|
estimated_position_value = account_balance * suggested_position_pct
|
||||||
|
estimated_quantity = estimated_position_value / entry_price if entry_price > 0 else 0
|
||||||
|
|
||||||
|
# 计算基于保证金的止损止盈
|
||||||
|
stop_loss_pct_margin = config.TRADING_CONFIG.get('STOP_LOSS_PERCENT', 0.03)
|
||||||
|
take_profit_pct_margin = config.TRADING_CONFIG.get('TAKE_PROFIT_PERCENT', 0.05)
|
||||||
|
|
||||||
stop_loss_price = self.risk_manager.get_stop_loss_price(
|
stop_loss_price = self.risk_manager.get_stop_loss_price(
|
||||||
entry_price,
|
entry_price,
|
||||||
direction,
|
direction,
|
||||||
|
estimated_quantity,
|
||||||
|
leverage,
|
||||||
|
stop_loss_pct=stop_loss_pct_margin,
|
||||||
klines=symbol_info.get('klines'),
|
klines=symbol_info.get('klines'),
|
||||||
bollinger=symbol_info.get('bollinger'),
|
bollinger=symbol_info.get('bollinger'),
|
||||||
atr=symbol_info.get('atr')
|
atr=symbol_info.get('atr')
|
||||||
)
|
)
|
||||||
|
|
||||||
# 计算止损百分比
|
# 计算止损百分比(相对于保证金,用于显示)
|
||||||
|
estimated_margin = estimated_position_value / leverage if leverage > 0 else estimated_position_value
|
||||||
|
stop_loss_amount = estimated_margin * stop_loss_pct_margin
|
||||||
if direction == 'BUY':
|
if direction == 'BUY':
|
||||||
stop_loss_pct = (entry_price - stop_loss_price) / entry_price
|
stop_loss_pct = (entry_price - stop_loss_price) / entry_price
|
||||||
else:
|
else:
|
||||||
stop_loss_pct = (stop_loss_price - entry_price) / entry_price
|
stop_loss_pct = (stop_loss_price - entry_price) / entry_price
|
||||||
|
|
||||||
# 第一目标:盈亏比1:1
|
# 第一目标:盈亏比1:1(相对于保证金)
|
||||||
if direction == 'BUY':
|
take_profit_1_pct_margin = stop_loss_pct_margin * 1.0 # 1:1 盈亏比
|
||||||
take_profit_1 = entry_price + (entry_price - stop_loss_price)
|
take_profit_1 = self.risk_manager.get_take_profit_price(
|
||||||
else:
|
entry_price, direction, estimated_quantity, leverage,
|
||||||
take_profit_1 = entry_price - (stop_loss_price - entry_price)
|
take_profit_pct=take_profit_1_pct_margin
|
||||||
|
)
|
||||||
|
|
||||||
# 第二目标:止损的2.5倍
|
# 第二目标:止损的2.5倍(相对于保证金)
|
||||||
take_profit_2_pct = stop_loss_pct * 2.5
|
take_profit_2_pct_margin = stop_loss_pct_margin * 2.5
|
||||||
take_profit_2 = self.risk_manager.get_take_profit_price(
|
take_profit_2 = self.risk_manager.get_take_profit_price(
|
||||||
entry_price, direction, take_profit_pct=take_profit_2_pct
|
entry_price, direction, estimated_quantity, leverage,
|
||||||
|
take_profit_pct=take_profit_2_pct_margin
|
||||||
)
|
)
|
||||||
|
|
||||||
# 建议仓位(根据信号强度调整)
|
# 建议仓位(根据信号强度调整)
|
||||||
|
|
@ -421,11 +443,15 @@ class TradeRecommender:
|
||||||
base_win_rate -= 2
|
base_win_rate -= 2
|
||||||
estimated_win_rate = max(35, min(75, base_win_rate))
|
estimated_win_rate = max(35, min(75, base_win_rate))
|
||||||
|
|
||||||
# 计算盈亏USDT评估
|
# 计算盈亏USDT评估(基于保证金)
|
||||||
position_value = account_balance * suggested_position_pct * config.TRADING_CONFIG.get('LEVERAGE', 10)
|
position_value = account_balance * suggested_position_pct
|
||||||
stop_loss_usdt = position_value * stop_loss_pct
|
margin = position_value / leverage if leverage > 0 else position_value
|
||||||
take_profit_1_usdt = position_value * stop_loss_pct
|
|
||||||
take_profit_2_usdt = position_value * take_profit_2_pct
|
# 止损止盈金额(相对于保证金)
|
||||||
|
stop_loss_usdt = margin * stop_loss_pct_margin
|
||||||
|
take_profit_1_usdt = margin * take_profit_1_pct_margin
|
||||||
|
take_profit_2_usdt = margin * take_profit_2_pct_margin
|
||||||
|
|
||||||
expected_pnl_1 = (estimated_win_rate / 100) * take_profit_1_usdt - ((100 - estimated_win_rate) / 100) * stop_loss_usdt
|
expected_pnl_1 = (estimated_win_rate / 100) * take_profit_1_usdt - ((100 - estimated_win_rate) / 100) * stop_loss_usdt
|
||||||
expected_pnl_2 = (estimated_win_rate / 100) * take_profit_2_usdt - ((100 - estimated_win_rate) / 100) * stop_loss_usdt
|
expected_pnl_2 = (estimated_win_rate / 100) * take_profit_2_usdt - ((100 - estimated_win_rate) / 100) * stop_loss_usdt
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user