Strategies
多维度自适应移动平均矩阵与ATR动态精准交易策略-Multi-Dimensional-Adaptive-Moving-Average-Matrix-with-ATR-Powered-Precision-Trading-Strategy
ianzeng123 · PineScript · Trend Following · 2025-04-16 15:50:36
Trigger
Filter
Sizing
Exit
—
Context terms
No English write-up in the source (no author description).
Source code (291 lines)
/*backtest
start: 2024-04-16 00:00:00
end: 2025-04-15 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=6
strategy("Dskyz (DAFE) MAtrix with ATR-Powered Precision",
overlay=true,
default_qty_type=strategy.fixed,
initial_capital=1000000,
commission_value=0,
slippage=1,
pyramiding=10)
// ==================================================================
// USER-DEFINED FUNCTIONS
// ==================================================================
// Hull Moving Average (HMA)
hma(src, len) =>
halfLen = math.round(len * 0.5)
sqrtLen = math.round(math.sqrt(len))
wmaf = ta.wma(src, halfLen)
wmaFull = ta.wma(src, len)
ta.wma(2 * wmaf - wmaFull, sqrtLen)
// Triple Exponential Moving Average (TEMA)
tema(src, len) =>
ema1 = ta.ema(src, len)
ema2 = ta.ema(ema1, len)
ema3 = ta.ema(ema2, len)
3 * (ema1 - ema2) + ema3
// Double Exponential Moving Average (DEMA)
dema(src, len) =>
ema1 = ta.ema(src, len)
ema2 = ta.ema(ema1, len)
2 * ema1 - ema2
// VWMA - Volume Weighted Moving Average
vwma(src, len) =>
ta.vwma(src, len)
// ZLEMA - Zero Lag EMA
zlema(src, len) =>
lag = math.floor((len - 1) / 2)
ta.ema(2 * src - src[lag], len)
// ALMA - Arnaud Legoux Moving Average
alma(src, len, offset=0.85, sigma=6) =>
ta.alma(src, len, offset, sigma)
// Custom Kaufman Adaptive Moving Average (KAMA)
kama(src, len) =>
fastSC = 2.0 / (2 + 1)
slowSC = 2.0 / (30 + 1)
change = math.abs(src - src[len])
volatility = 0.0
for i = 0 to len - 1
volatility += math.abs(src - src[i])
er = volatility != 0 ? change / volatility : 0.0
sc = math.pow(er * (fastSC - slowSC) + slowSC, 2)
var float kama_val = na
kama_val := na(kama_val) ? ta.sma(src, len) : kama_val + sc * (src - kama_val)
kama_val
// ==================================================================
// INPUTS
// ==================================================================
fastLength = input.int(9, "[MA] Fast MA Length", minval=1)
slowLength = input.int(19, "[MA] Slow MA Length", minval=1)
fastMAType = input.string("SMA", "Fast MA Type", options=["SMA", "EMA", "SMMA", "HMA", "TEMA", "WMA", "VWMA", "ZLEMA", "ALMA", "KAMA", "DEMA"])
slowMAType = input.string("SMA", "Slow MA Type", options=["SMA", "EMA", "SMMA", "HMA", "TEMA", "WMA", "VWMA", "ZLEMA", "ALMA", "KAMA", "DEMA"])
atrPeriod = input.int(14, "ATR Period", minval=1)
atrMultiplier = input.float(1.5, "ATR Multiplier for Filter", minval=0.1, step=0.1)
useTrendFilter = input.bool(true, "[Filter Settings] Use 15m Trend Filter")
minVolume = input.int(10, "Minimum Volume", minval=1)
volatilityThreshold = input.float(1.0, "Volatility Threshold (%)", minval=0.1, step=0.1) / 100
tradingStartHour = input.int(9, "Trading Start Hour (24h)", minval=0, maxval=23)
tradingEndHour = input.int(16, "Trading End Hour (24h)", minval=0, maxval=23)
trailOffset = input.float(0.5, "[Exit Settings] Trailing Stop Offset ATR Multiplier", minval=0.01, step=0.01)
profitTargetATRMult = input.float(1.2, "Profit Target ATR Multiplier", minval=0.1, step=0.1)
fixedStopMultiplier = input.float(1.3, "Fixed Stop Multiplier", minval=0.5, step=0.1)
fixedQuantity = input.int(2, "Trade Quantity", minval=1)
resetDashboard = input.bool(false, "Reset Dashboard Stats")
// ==================================================================
// CALCULATIONS
// ==================================================================
volumeOk = volume >= minVolume
currentHour = hour(time)
timeWindow = currentHour >= tradingStartHour and currentHour <= tradingEndHour
volumeSpike = volume > 1.2 * ta.sma(volume, 10)
// ATR Calculation
atr = ta.atr(atrPeriod)
volatility = nz(atr / close, 0)
volatilityOk = volatility <= volatilityThreshold
// ==================================================================
// MOVING AVERAGES CALCULATIONS
// ==================================================================
var float fastMA = na
var float slowMA = na
// Fast MA Logic
if fastMAType == "SMA"
fastMA := ta.sma(close, fastLength)
else if fastMAType == "EMA"
fastMA := ta.ema(close, fastLength)
else if fastMAType == "SMMA"
fastMA := ta.rma(close, fastLength)
else if fastMAType == "HMA"
fastMA := hma(close, fastLength)
else if fastMAType == "TEMA"
fastMA := tema(close, fastLength)
else if fastMAType == "WMA"
fastMA := ta.wma(close, fastLength)
else if fastMAType == "VWMA"
fastMA := vwma(close, fastLength)
else if fastMAType == "ZLEMA"
fastMA := zlema(close, fastLength)
else if fastMAType == "ALMA"
fastMA := alma(close, fastLength)
else if fastMAType == "KAMA"
fastMA := kama(close, fastLength)
else if fastMAType == "DEMA"
fastMA := dema(close, fastLength)
// Slow MA Logic
if slowMAType == "SMA"
slowMA := ta.sma(close, slowLength)
else if slowMAType == "EMA"
slowMA := ta.ema(close, slowLength)
else if slowMAType == "SMMA"
slowMA := ta.rma(close, slowLength)
else if slowMAType == "HMA"
slowMA := hma(close, slowLength)
else if slowMAType == "TEMA"
slowMA := tema(close, slowLength)
else if slowMAType == "WMA"
slowMA := ta.wma(close, slowLength)
else if slowMAType == "VWMA"
slowMA := vwma(close, slowLength)
else if slowMAType == "ZLEMA"
slowMA := zlema(close, slowLength)
else if slowMAType == "ALMA"
slowMA := alma(close, slowLength)
else if slowMAType == "KAMA"
slowMA := kama(close, slowLength)
else if slowMAType == "DEMA"
slowMA := dema(close, slowLength)
// ==================================================================
// TREND FILTER & SIGNAL LOGIC
// ==================================================================
// Retrieve 15-minute MAs for trend filtering
[fastMA15m, slowMA15m] = request.security(syminfo.tickerid, "15", [ta.sma(close, fastLength), ta.sma(close, slowLength)])
trend15m = fastMA15m > slowMA15m ? 1 : fastMA15m < slowMA15m ? -1 : 0
trendLongOk = not useTrendFilter or trend15m >= 0
trendShortOk= not useTrendFilter or trend15m <= 0
// ATR-based Price Filter
atrFilterLong = close > slowMA + atr * atrMultiplier
atrFilterShort = close < slowMA - atr * atrMultiplier
// Signal Logic: MA alignment + filters
maAbove = close > fastMA and fastMA > slowMA
maBelow = close < fastMA and fastMA < slowMA
longCondition = maAbove and trendLongOk and atrFilterLong and volumeOk and volumeSpike and timeWindow and volatilityOk
shortCondition= maBelow and trendShortOk and atrFilterShort and volumeOk and volumeSpike and timeWindow and volatilityOk
// ==================================================================
// ENTRY LOGIC
// ==================================================================
if strategy.position_size == 0 and longCondition
strategy.entry("Long", strategy.long, qty=fixedQuantity)
if strategy.position_size == 0 and shortCondition
strategy.entry("Short", strategy.short, qty=fixedQuantity)
// ==================================================================
// EXIT LOGIC
// ==================================================================
if strategy.position_size > 0
strategy.exit("Long Exit", "Long",
stop = strategy.position_avg_price - atr * fixedStopMultiplier,
limit = strategy.position_avg_price + atr * profitTargetATRMult,
trail_offset = atr * trailOffset,
trail_points = atr * trailOffset)
if strategy.position_size < 0
strategy.exit("Short Exit", "Short",
stop = strategy.position_avg_price + atr * fixedStopMultiplier,
limit = strategy.position_avg_price - atr * profitTargetATRMult,
trail_offset = atr * trailOffset,
trail_points = atr * trailOffset)
// ==================================================================
// VISUALS: PLOT MAs
// ==================================================================
plot(fastMA, color=color.blue, linewidth=2, title="Fast MA")
plot(slowMA, color=color.red, linewidth=2, title="Slow MA")
// ==================================================================
// METRICS CALCULATIONS (for Dashboard)
// ==================================================================
// Additional metrics:
atrPct = close != 0 ? (atr / close) * 100 : na // ATR as percentage of Close
maGapPct = (slowMA != 0) ? (math.abs(fastMA - slowMA) / slowMA) * 100 : na // % difference between MAs
// Open PnL Calculation
currentPnL = strategy.position_size != 0 ? (close - strategy.position_avg_price) * strategy.position_size : 0
// Persistent variable for highest equity (for drawdown calculation)
var float highestEquity = strategy.equity
highestEquity := math.max(highestEquity, strategy.equity)
totalDrawdown = strategy.equity - highestEquity
// Reset dashboard metrics if reset toggle is on.
if resetDashboard
highestEquity := strategy.equity
// ==================================================================
// DASHBOARD: WATERMARK LOGO (Bottom-Right)
// ==================================================================
var table watermarkTable = table.new(position.bottom_right, 1, 1, bgcolor=color.rgb(0, 0, 0, 80), border_color=color.rgb(0, 50, 137), border_width=1)
if barstate.islast
table.cell(watermarkTable, 0, 0, "⚡ Dskyz - DAFE Trading Systems", text_color=color.rgb(159, 127, 255, 80), text_size=size.large)
// ==================================================================
// DASHBOARD: METRICS TABLE (Bottom-Left)
// ==================================================================
var table dashboard = table.new(position.middle_right, 2, 12, bgcolor=color.new(#000000, 29), border_color=color.rgb(80, 80, 80), border_width=1)
if barstate.islast
// Row 0 – Dashboard Title (duplicated in both columns to simulate spanning)
table.cell(dashboard, 0, 0, "⚡(DAFE) Trading Systems", text_color=color.rgb(135, 135, 135), text_size=size.small)
// Row 1 – Position
table.cell(dashboard, 0, 1, "Position", text_color=color.gray)
positionText = strategy.position_size > 0 ? "Long" : strategy.position_size < 0 ? "Short" : "Flat"
table.cell(dashboard, 1, 1, positionText, text_color=strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : color.blue)
// Row 2 – Current PnL
table.cell(dashboard, 0, 2, "Current P/L", text_color=color.gray)
table.cell(dashboard, 1, 2, str.tostring(currentPnL, "#.##"), text_color=(currentPnL > 0 ? color.green : currentPnL < 0 ? color.red : color.gray))
// Row 3 – Equity
table.cell(dashboard, 0, 3, "Equity", text_color=color.gray)
table.cell(dashboard, 1, 3, str.tostring(strategy.equity, "#.##"), text_color=color.white)
// Row 4 – Closed Trades
table.cell(dashboard, 0, 4, "Closed Trades", text_color=color.gray)
table.cell(dashboard, 1, 4, str.tostring(strategy.closedtrades), text_color=color.white)
// Row 5 – Title Step
table.cell(dashboard, 0, 5, "Metrics", text_color=color.rgb(76, 122, 23))
// Row 6 – Fast MA
table.cell(dashboard, 0, 6, "Fast MA", text_color=color.gray)
table.cell(dashboard, 1, 6, str.tostring(fastMA, "#.##"), text_color=color.white)
// Row 7 – Slow MA
table.cell(dashboard, 0, 7, "Slow MA", text_color=color.gray)
table.cell(dashboard, 1, 7, str.tostring(slowMA, "#.##"), text_color=color.white)
// Row 8 – ATR (Raw)
table.cell(dashboard, 0, 8, "ATR", text_color=color.gray)
table.cell(dashboard, 1, 8, str.tostring(atr, "#.##"), text_color=color.white)
// Row 9 – ATR (%)
table.cell(dashboard, 0, 9, "ATR (%)", text_color=color.gray)
table.cell(dashboard, 1, 9, str.tostring(atrPct, "#.##") + "%", text_color=color.white)
// Row 10 – MA Gap (%)
table.cell(dashboard, 0, 10, "MA Gap (%)", text_color=color.gray)
table.cell(dashboard, 1, 10, na(maGapPct) ? "N/A" : str.tostring(maGapPct, "#.##") + "%", text_color=color.white)
// Row 11 – Volatility (%)
table.cell(dashboard, 0, 11, "Volatility (%)", text_color=color.gray)
table.cell(dashboard, 1, 11, str.tostring(volatility * 100, "#.##") + "%", text_color=color.white)