动态狙击系统 v3.0 - 激进复利版


创建日期: 2025-12-06 14:59:10 最后修改: 2025-12-06 15:03:50
复制: 0 点击次数: 19
avatar of QCoder QCoder
11
关注
607
关注者
策略源码
//@version=5
strategy("动态狙击系统 v3.0 - 激进复利版",
     overlay=true,
     initial_capital=100000,
     default_qty_type=strategy.fixed,
     commission_type=strategy.commission.percent,
     commission_value=0.075,
     slippage=3,
     pyramiding=0,
     calc_on_every_tick=true,
     process_orders_on_close=false,
     max_bars_back=500)

// ==================== 激进版核心参数 ====================

// 你的激进风控配置
riskPercentage = input.float(3.0, "单笔风险比例(%)", minval=1.0, maxval=5.0, step=0.1, group="激进风控")
maxLeverage = input.float(1.5, "牛市最大杠杆倍数", minval=1.0, maxval=2.0, step=0.1, group="激进风控")
compoundingMode = input.bool(true, "启用复利模式", group="激进风控")
maxPositionPct = input.float(15.0, "最大仓位占比(%)", minval=10, maxval=25, group="激进风控")

// 你的激进止盈配置
breakEvenR = input.float(1.2, "延迟保本触发R", minval=0.8, maxval=2.0, step=0.1, group="激进止盈")
lockSmallR = input.float(3.0, "延迟锁利触发R", minval=2.0, maxval=5.0, step=0.1, group="激进止盈")
lockSmallLevel = input.float(1.0, "锁利位置R", minval=0.5, maxval=2.0, step=0.1, group="激进止盈")
lockBigR = input.float(6.0, "大利润触发R", minval=4.0, maxval=10.0, step=0.1, group="激进止盈")
lockBigLevel = input.float(3.0, "大利润位置R", minval=2.0, maxval=5.0, step=0.1, group="激进止盈")

// 利润回撤保护(激进版放宽)
useGivebackKill = input.bool(true, "启用利润回撤熔断", group="激进止盈")
givebackStartR = input.float(4.0, "回撤监控起始R", minval=3, maxval=8, step=0.5, group="激进止盈")
maxGivebackR = input.float(2.0, "最大允许回撤R", minval=1.0, maxval=4.0, step=0.5, group="激进止盈")

// 趋势过滤
trendEmaLength = input.int(50, "日线EMA周期", minval=20, maxval=100, group="趋势过滤")
trendLookback = input.int(20, "动量回看周期", minval=10, maxval=50, group="趋势过滤")
trendThreshold = input.float(5.0, "趋势阈值(%)", minval=2, maxval=15, group="趋势过滤")

// 入场设置
valueEmaLength = input.int(20, "4H EMA周期", minval=10, maxval=50, group="入场设置")
atrLength = input.int(14, "ATR周期", minval=7, maxval=21, group="入场设置")
pullbackAtrMult = input.float(1.2, "回调区ATR倍数", minval=0.5, maxval=2.0, group="入场设置")

// 止损设置
stopAtrMult = input.float(3.0, "止损ATR倍数", minval=2.0, maxval=5.0, group="风险管理")

// 激进版熔断(放宽限制)
dailyLossLimit = input.float(5.0, "日亏损熔断(%)", minval=3, maxval=8, group="熔断保护")
totalDrawdownLimit = input.float(25.0, "总回撤防御(%)", minval=15, maxval=35, group="熔断保护")

// ==================== 数据获取 ====================

// 日线数据
dailyClose = request.security(syminfo.tickerid, "D", close, lookahead=barmerge.lookahead_off)
dailyClose20Ago = request.security(syminfo.tickerid, "D", close[trendLookback], lookahead=barmerge.lookahead_off)
dailyEma50 = request.security(syminfo.tickerid, "D", ta.ema(close, trendEmaLength), lookahead=barmerge.lookahead_off)

// 当前周期数据
h4Ema20 = ta.ema(close, valueEmaLength)
h4Atr = ta.atr(atrLength)

// ==================== 趋势过滤器 ====================

trendMomentum = (dailyClose - dailyClose20Ago) / dailyClose20Ago * 100
isBullishEnv = dailyClose > dailyEma50 and trendMomentum > trendThreshold
isBearishEnv = dailyClose < dailyEma50 and trendMomentum < -trendThreshold
isNoTradeZone = not isBullishEnv and not isBearishEnv

// ==================== 回调区识别 ====================

distanceToEma = math.abs(close - h4Ema20) / h4Atr
isBullPullback = isBullishEnv and close <= h4Ema20 + pullbackAtrMult * h4Atr and close >= h4Ema20 - pullbackAtrMult * h4Atr
isBearPullback = isBearishEnv and close >= h4Ema20 - pullbackAtrMult * h4Atr and close <= h4Ema20 + pullbackAtrMult * h4Atr

// ==================== 入场信号识别 ====================

bodySize = math.abs(close - open)
upperWick = high - math.max(close, open)
lowerWick = math.min(close, open) - low

isBullishCandle = close > open
isBearishCandle = close < open
isHammer = lowerWick >= bodySize * 1.2 and upperWick < bodySize * 0.5
isShootingStar = upperWick >= bodySize * 1.2 and lowerWick < bodySize * 0.5

// 做多信号
bullSignal1 = isBullishCandle and low < h4Ema20 and close >= h4Ema20
bullSignal2 = isHammer and low < h4Ema20
bullSignal3 = isBullishCandle and close > close[1] and distanceToEma < pullbackAtrMult
bullEntrySignal = isBullPullback and (bullSignal1 or bullSignal2 or bullSignal3)

// 做空信号
bearSignal1 = isBearishCandle and high > h4Ema20 and close <= h4Ema20
bearSignal2 = isShootingStar and high > h4Ema20
bearSignal3 = isBearishCandle and close < close[1] and distanceToEma < pullbackAtrMult
bearEntrySignal = isBearPullback and (bearSignal1 or bearSignal2 or bearSignal3)

// ==================== 核心:激进复利仓位计算 ====================

// 计算累计盈利率(用于杠杆触发条件)
cumulativeProfitPct = (strategy.equity - strategy.initial_capital) / strategy.initial_capital * 100

// 复利基数:使用当前权益而非初始资金
capitalBase = compoundingMode ? strategy.equity : strategy.initial_capital

// 基础风险金额(你的3%配置)
baseRiskAmount = capitalBase * riskPercentage / 100

// 杠杆触发条件:累计盈利>10%且当前是牛市
useLeverage = compoundingMode and cumulativeProfitPct >= 10.0 and isBullishEnv

// 应用杠杆倍数
effectiveLeverage = useLeverage ? maxLeverage : 1.0
leveragedRiskAmount = baseRiskAmount * effectiveLeverage

// 止损距离
stopDistance = stopAtrMult * h4Atr

// 计算合约数量
contractSize = leveragedRiskAmount / stopDistance

// 仓位占比限制
nominalValue = contractSize * close
positionPct = nominalValue / strategy.equity * 100

// 如果超过最大仓位占比,强制缩小
if positionPct > maxPositionPct
    contractSize := strategy.equity * maxPositionPct / 100 / close

// 最终合约数
finalContractSize = math.floor(contractSize * 1000) / 1000
actualRiskAmount = finalContractSize * stopDistance

// ==================== 风控熔断机制 ====================

var float dayStartEquity = strategy.initial_capital
if ta.change(time("D"))
    dayStartEquity := strategy.equity

dailyPnL = strategy.equity - dayStartEquity
dailyPnLPct = dailyPnL / strategy.equity * 100
isDailyCircuitBreaker = dailyPnLPct <= -dailyLossLimit

var float peakEquity = strategy.initial_capital
if strategy.equity > peakEquity
    peakEquity := strategy.equity

currentDrawdown = (peakEquity - strategy.equity) / peakEquity * 100
isDefenseMode = currentDrawdown >= totalDrawdownLimit

// ==================== 持仓状态管理 ====================

var float entryPrice = na
var float currentStopLoss = na
var float riskUnit = na
var int profitStage = 0
var float maxR = 0.0

bool hasPosition = strategy.position_size != 0
bool isLong = strategy.position_size > 0
bool isShort = strategy.position_size < 0

// ==================== 开仓逻辑 ====================

canOpenLong = bullEntrySignal and not hasPosition and not isDailyCircuitBreaker and not isNoTradeZone and not isDefenseMode
canOpenShort = bearEntrySignal and not hasPosition and not isDailyCircuitBreaker and not isNoTradeZone and not isDefenseMode

if canOpenLong and finalContractSize > 0
    leverageText = effectiveLeverage > 1.0 ? " [杠杆:" + str.tostring(effectiveLeverage, "#.#") + "x]" : ""
    strategy.entry("Long", strategy.long, qty=finalContractSize,
         comment="激进多单 $" + str.tostring(actualRiskAmount, "#") + leverageText)
    entryPrice := close
    currentStopLoss := close - stopDistance
    riskUnit := stopDistance
    profitStage := 0
    maxR := 0.0

if canOpenShort and finalContractSize > 0
    leverageText = effectiveLeverage > 1.0 ? " [杠杆:" + str.tostring(effectiveLeverage, "#.#") + "x]" : ""
    strategy.entry("Short", strategy.short, qty=finalContractSize,
         comment="激进空单 $" + str.tostring(actualRiskAmount, "#") + leverageText)
    entryPrice := close
    currentStopLoss := close + stopDistance
    riskUnit := stopDistance
    profitStage := 0
    maxR := 0.0

// ==================== 激进分级止盈逻辑 ====================

currentR = 0.0

if isLong and not na(entryPrice)
    currentR := (close - entryPrice) / riskUnit
    maxR := math.max(maxR, currentR)
    
    // 阶段1:延迟保本(1.2R)- 你的配置
    if currentR >= breakEvenR and profitStage < 1
        currentStopLoss := math.max(currentStopLoss, entryPrice)
        profitStage := 1
    
    // 阶段2:延迟锁利(3R锁1R)- 你的配置
    if currentR >= lockSmallR and profitStage < 2
        currentStopLoss := math.max(currentStopLoss, entryPrice + lockSmallLevel * riskUnit)
        profitStage := 2
    
    // 阶段3:大利润锁定(6R锁3R)- 你的配置
    if currentR >= lockBigR and profitStage < 3
        currentStopLoss := math.max(currentStopLoss, entryPrice + lockBigLevel * riskUnit)
        profitStage := 3
    
    // 利润回撤熔断(4R后回撤2R就平仓)
    if useGivebackKill and maxR >= givebackStartR and (maxR - currentR) >= maxGivebackR
        strategy.close("Long", comment="回撤熔断 峰值:" + str.tostring(maxR, "#.#") + "R")
        entryPrice := na
        profitStage := 0
        maxR := 0.0
    // 实时止损检查
    else if close <= currentStopLoss
        strategy.close("Long", comment="止损 R:" + str.tostring(currentR, "#.#"))
        entryPrice := na
        profitStage := 0
        maxR := 0.0
    // 趋势终结强平
    else if dailyClose < dailyEma50
        strategy.close("Long", comment="趋势终结 R:" + str.tostring(currentR, "#.#"))
        entryPrice := na
        profitStage := 0
        maxR := 0.0

if isShort and not na(entryPrice)
    currentR := (entryPrice - close) / riskUnit
    maxR := math.max(maxR, currentR)
    
    if currentR >= breakEvenR and profitStage < 1
        currentStopLoss := math.min(currentStopLoss, entryPrice)
        profitStage := 1
    
    if currentR >= lockSmallR and profitStage < 2
        currentStopLoss := math.min(currentStopLoss, entryPrice - lockSmallLevel * riskUnit)
        profitStage := 2
    
    if currentR >= lockBigR and profitStage < 3
        currentStopLoss := math.min(currentStopLoss, entryPrice - lockBigLevel * riskUnit)
        profitStage := 3
    
    if useGivebackKill and maxR >= givebackStartR and (maxR - currentR) >= maxGivebackR
        strategy.close("Short", comment="回撤熔断 峰值:" + str.tostring(maxR, "#.#") + "R")
        entryPrice := na
        profitStage := 0
        maxR := 0.0
    else if close >= currentStopLoss
        strategy.close("Short", comment="止损 R:" + str.tostring(currentR, "#.#"))
        entryPrice := na
        profitStage := 0
        maxR := 0.0
    else if dailyClose > dailyEma50
        strategy.close("Short", comment="趋势终结 R:" + str.tostring(currentR, "#.#"))
        entryPrice := na
        profitStage := 0
        maxR := 0.0

// ==================== 图表显示 ====================

plot(dailyEma50, "日线EMA50", color=color.orange, linewidth=2)
plot(h4Ema20, "4H EMA20", color=color.blue, linewidth=1)

upperBand = h4Ema20 + pullbackAtrMult * h4Atr
lowerBand = h4Ema20 - pullbackAtrMult * h4Atr
plot(upperBand, "回调上轨", color=color.new(color.gray, 70))
plot(lowerBand, "回调下轨", color=color.new(color.gray, 70))

plot(hasPosition ? currentStopLoss : na, "动态止损", color=color.red, style=plot.style_linebr, linewidth=2)
plot(hasPosition ? entryPrice : na, "入场价", color=color.white, style=plot.style_linebr, linewidth=1)

// 背景色:杠杆模式用深绿,普通牛市浅绿,熊市红色
bgColor = useLeverage ? color.new(color.green, 80) :
         isBullishEnv ? color.new(color.green, 95) :
         isBearishEnv ? color.new(color.red, 95) :
         color.new(color.gray, 97)
bgcolor(bgColor)

plotshape(canOpenLong, "做多", shape.triangleup, location.belowbar, color.lime, size=size.small)
plotshape(canOpenShort, "做空", shape.triangledown, location.abovebar, color.red, size=size.small)

// 杠杆启用标记
plotshape(useLeverage and not hasPosition, "杠杆模式", shape.diamond, location.top, color.yellow, size=size.tiny)

// ==================== 激进版Dashboard ====================

var table dashboard = table.new(position.top_right, 2, 12, bgcolor=color.new(color.black, 85), border_width=1)

if barstate.islast
    // 标题
    table.cell(dashboard, 0, 0, "激进复利版 v3.0", text_color=color.white, text_size=size.normal, bgcolor=color.new(color.red, 50))
    table.cell(dashboard, 1, 0, "高风险高回报", text_color=color.yellow, text_size=size.normal, bgcolor=color.new(color.red, 50))
    
    // 账户状态
    table.cell(dashboard, 0, 1, "当前权益", text_color=color.white, text_size=size.small)
    equityColor = strategy.equity > strategy.initial_capital ? color.lime : color.red
    table.cell(dashboard, 1, 1, "$" + str.tostring(strategy.equity, "#,###"), text_color=equityColor, text_size=size.small)
    
    // 累计盈利
    table.cell(dashboard, 0, 2, "累计盈利", text_color=color.white, text_size=size.small)
    profitColor = cumulativeProfitPct > 0 ? color.lime : color.red
    table.cell(dashboard, 1, 2, str.tostring(cumulativeProfitPct, "#.#") + "%", text_color=profitColor, text_size=size.small)
    
    // 杠杆状态
    table.cell(dashboard, 0, 3, "当前杠杆", text_color=color.white, text_size=size.small)
    leverageColor = effectiveLeverage > 1.0 ? color.yellow : color.gray
    leverageStatus = effectiveLeverage > 1.0 ? str.tostring(effectiveLeverage, "#.#") + "x 🚀" : "1.0x"
    table.cell(dashboard, 1, 3, leverageStatus, text_color=leverageColor, text_size=size.small)
    
    // 基础风险(3%)
    table.cell(dashboard, 0, 4, "基础风险", text_color=color.white, text_size=size.small)
    table.cell(dashboard, 1, 4, "$" + str.tostring(baseRiskAmount, "#") + " (3%)", text_color=color.aqua, text_size=size.small)
    
    // 实际风险(含杠杆)
    table.cell(dashboard, 0, 5, "实际风险", text_color=color.white, text_size=size.small)
    actualRiskColor = actualRiskAmount > baseRiskAmount ? color.orange : color.lime
    table.cell(dashboard, 1, 5, "$" + str.tostring(actualRiskAmount, "#"), text_color=actualRiskColor, text_size=size.small)
    
    // 趋势状态
    trendText = isBullishEnv ? "多头 ▲" : isBearishEnv ? "空头 ▼" : "震荡 ■"
    trendColor = isBullishEnv ? color.lime : isBearishEnv ? color.red : color.gray
    table.cell(dashboard, 0, 6, "趋势", text_color=color.white, text_size=size.small)
    table.cell(dashboard, 1, 6, trendText, text_color=trendColor, text_size=size.small)
    
    // 回调状态
    pullbackText = isBullPullback ? "回调区 ✓" : isBearPullback ? "反弹区 ✓" : "等待..."
    table.cell(dashboard, 0, 7, "回调", text_color=color.white, text_size=size.small)
    table.cell(dashboard, 1, 7, pullbackText, text_color=(isBullPullback or isBearPullback) ? color.yellow : color.gray, text_size=size.small)
    
    // 持仓状态
    posText = isLong ? "持多 ●" : isShort ? "持空 ●" : "空仓 ○"
    posColor = isLong ? color.lime : isShort ? color.red : color.gray
    table.cell(dashboard, 0, 8, "持仓", text_color=color.white, text_size=size.small)
    table.cell(dashboard, 1, 8, posText, text_color=posColor, text_size=size.small)
    
    // 当前R倍数
    table.cell(dashboard, 0, 9, "当前R", text_color=color.white, text_size=size.small)
    rColor = currentR > 0 ? color.lime : currentR < 0 ? color.red : color.gray
    table.cell(dashboard, 1, 9, str.tostring(currentR, "#.##") + "R", text_color=rColor, text_size=size.small)
    
    // 历史最高R
    table.cell(dashboard, 0, 10, "峰值R", text_color=color.white, text_size=size.small)
    table.cell(dashboard, 1, 10, str.tostring(maxR, "#.##") + "R", text_color=color.lime, text_size=size.small)
    
    // 止盈阶段
    stageText = profitStage == 0 ? "初始" : profitStage == 1 ? "已保本" : profitStage == 2 ? "锁小利" : "锁大利"
    table.cell(dashboard, 0, 11, "阶段", text_color=color.white, text_size=size.small)
    table.cell(dashboard, 1, 11, stageText, text_color=color.yellow, text_size=size.small)