本策略是一个基于市场疲劳度分析的多层级交易系统,通过对价格动态的深入分析来识别市场可能出现转折的关键时刻。该策略结合了动态的风险管理机制,包括资金管理、止损优化以及回撤控制等多个维度,形成了一个完整的交易决策框架。
策略核心是通过监测价格连续运动来判断市场疲劳程度。具体来说: 1. 通过比较当前收盘价与之前第4根K线的收盘价来确定趋势方向 2. 设置了三个不同强度级别(9/12/14)的信号触发点 3. 当价格持续朝一个方向运动时,系统会累积信号计数 4. 一旦达到预设的信号强度阈值,系统会给出相应级别的交易信号 5. 整合了基于ATR的动态止损机制和风险回报比的仓位管理系统
该策略通过多层级的疲劳度分析和完善的风险管理系统,为交易者提供了一个系统化的交易框架。虽然存在一些需要优化的地方,但整体设计理念完整,具有实际应用价值。建议在实盘中采用保守的资金管理策略,并持续进行参数优化和系统改进。
/*backtest
start: 2024-02-10 00:00:00
end: 2025-02-08 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=6
strategy(title="Improved Exhaustion Signal with Risk Management and Drawdown Control", shorttitle="Exhaustion Signal", overlay=true)
// ———————————————— INPUT SETTINGS ————————————————
showLevel1 = input.bool(true, 'Show Level 1 Signals')
showLevel2 = input.bool(true, 'Show Level 2 Signals')
showLevel3 = input.bool(true, 'Show Level 3 Signals')
// Thresholds for signal strength levels
level1 = 9
level2 = 12
level3 = 14
// Risk management inputs
riskPercentage = input.float(1.0, title="Risk Percentage per Trade", minval=0.1, maxval=5.0) // Risk per trade in percentage
riskRewardRatio = input.float(2.0, title="Risk-to-Reward Ratio", minval=1.0, maxval=5.0) // Reward-to-risk ratio
trailingStop = input.bool(true, title="Enable Trailing Stop") // Enable/Disable trailing stop
trailingStopDistance = input.int(50, title="Trailing Stop Distance (in points)", minval=1) // Distance for trailing stop
// Drawdown protection settings
maxDrawdown = input.float(10.0, title="Max Drawdown Percentage", minval=0.1, maxval=50.0) // Max allowable drawdown before stopping trading
// ———————————————— GLOBAL VARIABLES ————————————————
var int cycle = 0
var int bullishSignals = 0
var int bearishSignals = 0
var float equityHigh = na // Initialize as undefined
// Track equity drawdown
if (na(equityHigh) or strategy.equity > equityHigh)
equityHigh := strategy.equity
drawdownPercent = 100 * (equityHigh - strategy.equity) / equityHigh
// Stop trading if drawdown exceeds the limit
if drawdownPercent >= maxDrawdown
strategy.close_all()
// ———————————————— FUNCTION: RESET & IMMEDIATE RECHECK USING AN ARRAY RETURN ————————————————
f_resetAndRecheck(_bullish, _bearish, _cycle, _close, _close4) =>
newBullish = _bullish
newBearish = _bearish
newCycle = _cycle
// Reset cycle if necessary based on price action
newBullish := 0
newBearish := 0
newCycle := 0
if _close < _close4
newBullish := 1
newCycle := newBullish
else if _close > _close4
newBearish := 1
newCycle := newBearish
resultArray = array.new_int(3, 0)
array.set(resultArray, 0, newBullish)
array.set(resultArray, 1, newBearish)
array.set(resultArray, 2, newCycle)
resultArray
// ———————————————— EXHAUSTION LOGIC ————————————————
if cycle < 9
// Bullish cycle: close < close[4]
if close < close[4]
bullishSignals += 1
bearishSignals := 0
cycle := bullishSignals
// Bearish cycle: close > close[4]
else if close > close[4]
bearishSignals += 1
bullishSignals := 0
cycle := bearishSignals
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
else
// ——— BULLISH checks ———
if bullishSignals > 0
if bullishSignals < (level3 - 1)
if close < close[3]
bullishSignals += 1
bearishSignals := 0
cycle := bullishSignals
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
else if bullishSignals == (level3 - 1)
if close < close[2]
bullishSignals := level3
cycle := bullishSignals
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
// ——— BEARISH checks ———
else if bearishSignals > 0
if bearishSignals < (level3 - 1)
if close > close[3]
bearishSignals += 1
bullishSignals := 0
cycle := bearishSignals
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
else if bearishSignals == (level3 - 1)
if close > close[2]
bearishSignals := level3
cycle := bearishSignals
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
else
newVals = f_resetAndRecheck(bullishSignals, bearishSignals, cycle, close, close[4])
bullishSignals := array.get(newVals, 0)
bearishSignals := array.get(newVals, 1)
cycle := array.get(newVals, 2)
// ———————————————— SIGNAL FLAGS ————————————————
bullishLevel1 = showLevel1 and (bullishSignals == level1)
bearishLevel1 = showLevel1 and (bearishSignals == level1)
bullishLevel2 = showLevel2 and (bullishSignals == level2)
bearishLevel2 = showLevel2 and (bearishSignals == level2)
bullishLevel3 = showLevel3 and (bullishSignals == level3)
bearishLevel3 = showLevel3 and (bearishSignals == level3)
// ———————————————— PLOT SIGNALS ————————————————
plotshape(bullishLevel1, style=shape.diamond, color=color.new(#30ff85, 0), textcolor=color.white, size=size.tiny, location=location.belowbar, title="Level 1 Bullish Signal")
plotshape(bearishLevel1, style=shape.diamond, color=color.new(#ff1200, 0), textcolor=color.white, size=size.tiny, location=location.abovebar, title="Level 1 Bearish Signal")
plotshape(bullishLevel2, style=shape.xcross, color=color.new(#30ff85, 0), textcolor=color.white, size=size.tiny, location=location.belowbar, title="Level 2 Bullish Signal")
plotshape(bearishLevel2, style=shape.xcross, color=color.new(#ff1200, 0), textcolor=color.white, size=size.tiny, location=location.abovebar, title="Level 2 Bearish Signal")
plotshape(bullishLevel3, style=shape.flag, color=color.new(#30ff85, 0), textcolor=color.white, size=size.tiny, location=location.belowbar, title="Level 3 Bullish Signal")
plotshape(bearishLevel3, style=shape.flag, color=color.new(#ff1200, 0), textcolor=color.white, size=size.tiny, location=location.abovebar, title="Level 3 Bearish Signal")
// ———————————————— RESET AFTER LEVEL 3 ————————————————
if bullishSignals == level3 or bearishSignals == level3
bullishSignals := 0
bearishSignals := 0
cycle := 0
// ———————————————— BACKTEST LOGIC ————————————————
// Set up basic long and short entry conditions based on signal levels
longCondition = bullishLevel1 or bullishLevel2 or bullishLevel3
shortCondition = bearishLevel1 or bearishLevel2 or bearishLevel3
// Calculate position size based on risk percentage
equity = strategy.equity
riskAmount = equity * riskPercentage / 100
atr = ta.atr(14)
stopLossLevel = atr * 1.5 // Using ATR for dynamic stop-loss
positionSize = riskAmount / stopLossLevel
// Initialize strategy logic
if longCondition
strategy.entry("Long", strategy.long, qty=positionSize)
if shortCondition
strategy.entry("Short", strategy.short, qty=positionSize)
// ———————————————— CONCRETE STOP LOSS AND TAKE PROFIT ————————————————
stopLoss = stopLossLevel
takeProfit = stopLoss * riskRewardRatio
// Apply stop loss and take profit to the strategy based on concrete price levels
strategy.exit("Exit Long", from_entry="Long", stop=close - stopLoss, limit=close + takeProfit)
strategy.exit("Exit Short", from_entry="Short", stop=close + stopLoss, limit=close - takeProfit)
// ———————————————— TRAILING STOP ————————————————
if trailingStop
strategy.exit("Exit Long Trailing", from_entry="Long", trail_price=close - trailingStopDistance, trail_offset=trailingStopDistance)
strategy.exit("Exit Short Trailing", from_entry="Short", trail_price=close + trailingStopDistance, trail_offset=trailingStopDistance)