多重时间框架零延迟趋势信号交易策略:基于ZLEMA的动态进出场系统

ZLEMA ATR EMA MTF RR TP SL
创建日期: 2025-05-20 14:45:41 最后修改: 2025-05-20 14:45:41
复制: 0 点击次数: 592
avatar of ianzeng123 ianzeng123
2
关注
319
关注者

多重时间框架零延迟趋势信号交易策略:基于ZLEMA的动态进出场系统 多重时间框架零延迟趋势信号交易策略:基于ZLEMA的动态进出场系统

概述

多重时间框架零延迟趋势信号交易策略是一种基于零延迟指数移动平均线(ZLEMA)的量化交易系统,旨在减少传统移动平均线的滞后性,提供更快速准确的趋势识别信号。该策略不仅结合了波动性通道来识别趋势变化,还集成了多种灵活的出场机制,包括风险回报比出场、利润目标出场、基于ATR的止损与止盈、动态追踪止损和均线穿越退出等。特别适合中长周期的交易,策略可配置为仅做多或双向交易,并提供零线再入场选项,极大提高了交易系统的适应性和风险管理能力。

策略原理

该策略的核心原理基于零延迟指数移动平均线(ZLEMA),这是一种通过消除或减少价格数据延迟来提高移动平均线反应速度的技术指标。具体实现步骤如下:

  1. 零延迟计算:策略首先计算ZLEMA,通过公式zlema = ta.ema(src + (src - src[lag]), length)实现,其中lag是基于长度的一半计算得出,这种方法有效减少了传统EMA中的滞后性。

  2. 趋势识别机制

    • 在ZLEMA基础上添加波动性通道(类似布林带),通道宽度由ATR的最高值乘以乘数决定
    • 当价格上穿上轨时,趋势变为向上(1)
    • 当价格下穿下轨时,趋势变为向下(-1)
    • 系统还提供连续5根K线ZLEMA方向一致的确认功能,通过zlemaUpTrendzlemaDownTrend变量实现
  3. 多样化入场条件

    • 基础做多入场:价格上穿上轨且在日期范围内
    • 进阶做多入场:基础条件加上ZLEMA持续5根K线上升的趋势确认
    • 做空入场:价格下穿下轨且在日期范围内(可选功能)
    • ZLEMA零线再入场:价格短暂回调后又回到ZLEMA之上,且仍处于做多趋势中
  4. 综合动态出场系统

    • 风险回报比利润目标:基于入场价和止损位计算特定风险回报比的目标价
    • ATR基础止损和止盈:使用ATR乘数动态计算止损和止盈位置
    • ATR追踪止损:随着价格移动而自动上移止损位
    • 盈亏平衡止损:当利润达到特定风险回报比时,止损移至入场价
    • 趋势反转出场:当趋势指标转向时自动退出
    • EMA出场:当价格穿越特定EMA时退出

策略优势

多重时间框架零延迟趋势信号交易策略具有显著的优势:

  1. 减少信号滞后性:通过ZLEMA技术,减少了传统移动平均线的延迟,使趋势识别更加及时,能够更早捕捉到趋势起点。

  2. 全面的风险管理系统:集成了多层次风险控制机制,从固定止损、ATR动态止损、追踪止损到盈亏平衡止损,为不同市场环境提供完善保护。

  3. 灵活的交易方向选择:可配置为仅做多策略或双向交易策略,适应不同市场偏好和监管环境。

  4. 再入场机制:通过ZLEMA零线再入场功能,在强势趋势中允许在短期回调后再次入场,最大化趋势收益。

  5. 多元化退出策略:针对不同市场状况提供多种退出方案,既可以通过利润目标锁定收益,也可以通过追踪止损让利润奔跑。

  6. 可视化辅助:通过趋势阴影、止损线、止盈线和趋势指示器等可视化元素,直观展示交易信号和风险管理位置。

  7. 详细的绩效统计:集成了交易统计表格,显示胜率、净利润、最大回撤等关键指标,方便策略评估和优化。

策略风险

尽管该策略设计合理,但仍然存在一些潜在风险需要注意:

  1. 参数敏感性:ZLEMA长度和ATR乘数等核心参数对策略表现影响显著,不当设置可能导致信号过多或过少。

  2. 震荡市场虚假信号:在没有明确趋势的震荡市场中,可能产生频繁的虚假信号,导致连续亏损。

  3. 趋势反转风险:虽然策略设计了多种退出机制,但在剧烈的趋势反转中,仍可能来不及退出而承受较大亏损。

  4. 过度拟合风险:多个参数的组合可能导致对历史数据过度拟合,而在未来市场环境中表现不佳。

  5. 长周期信号稀少:当使用较长的ZLEMA长度时,策略可能产生较少的交易信号,影响资金利用效率。

  6. 止损宽度挑战:基于ATR的止损在高波动市场可能过宽,导致单笔亏损过大;而在低波动市场可能过窄,导致频繁被触发。

缓解这些风险的方法包括:严格的参数回测和前向验证、结合市场状态指标避免在震荡市场交易、实施严格的资金管理规则、定期重新优化策略参数以适应市场变化。

策略优化方向

该策略还有多个优化空间,可从以下方向进一步提升性能:

  1. 动态参数自适应:开发自适应机制,根据市场波动性自动调整ZLEMA长度和ATR乘数,提高策略在不同市场环境的适应性。

  2. 市场状态过滤:引入市场状态指标(如ADX、波动率指标),仅在有利的市场条件下交易,避免在低效震荡市场中频繁交易。

  3. 多时间框架确认:结合更高时间框架的趋势方向,只在大趋势方向一致时入场,提高成功率。

  4. 交易量确认:整合交易量指标作为辅助确认,例如只有在交易量增加时才确认趋势变化信号。

  5. 机器学习优化:使用机器学习算法寻找最优参数组合和入场时机,尤其是可以训练模型预测哪些信号更可能成功。

  6. 季节性和时间过滤器:添加交易时段和日历过滤器,避开低效或高风险的交易时段。

  7. 相关资产关联分析:引入相关资产的相关性分析,在多资产同向确认时增强信号可信度。

这些优化方向不仅能提高策略的稳定性和盈利能力,还能降低风险,使其更适合不同的市场环境和个人风险偏好。

总结

多重时间框架零延迟趋势信号交易策略是一个全面而灵活的量化交易系统,通过零延迟指数移动平均线(ZLEMA)技术和波动性通道实现快速准确的趋势识别,并结合多层次的动态风险管理机制保护资金安全。该策略既可捕捉趋势初期的入场机会,也能在趋势发展中通过再入场机制最大化收益,同时提供多种退出策略适应不同市场环境。

策略的主要优势在于减少了信号滞后性、提供了全面的风险管理系统和灵活的交易配置选项。然而,使用者需要注意参数敏感性、震荡市场虚假信号和过度拟合等潜在风险。通过市场状态过滤、多时间框架确认和动态参数自适应等优化方向,可以进一步提升策略性能。

作为一个基于技术指标的量化交易系统,该策略特别适合中长期趋势交易,适用于各种金融市场。不过,任何策略都需要根据个人交易目标、风险承受能力和市场偏好进行个性化调整,并结合严格的资金管理原则应用于实际交易中。

策略源码
//@version=6
// Quant Trading Pro www.quanttradingpro.com
// #1 Strategy Optimizer on the chrome extension store Quant Trading Strategy Optimizer


strategy(title="Quant Trading Zero Lag Trend Signals (MTF) Strategy", shorttitle="QT0️⃣Zero Lag Signals Strategy", overlay=true, 
     commission_type=strategy.commission.percent, 
     commission_value=0.1, 
     slippage=3, 
     default_qty_type=strategy.percent_of_equity, 
     default_qty_value=100, 
     initial_capital=1000, 
     margin_long=0, 
     margin_short=0)

// === INPUT PARAMETERS ===

// 📌 1️⃣ Main Calculations
length = input.int(70, title="Length", minval=70, maxval=7000)
mult   = input.float(1.2, "Band Multiplier", group="Main Calculations")

// === 📊 Trade Data Toggles ===
showFloatingTable = input.bool(true, "Show Floating Stats Table?", group="Trade Data")
showTradeLog      = input.bool(false, "Show Trade Log Labels on Chart?", group="Trade Data")
enableCSVExport = input.bool(false, "Enable CSV Export", group="Trade Data")

// 📌 ZLEMA Trend Confirmation for Entries
useZlemaTrendConfirm = input.bool(false, "Use ZLEMA Trend Confirmation for entry?", group="Entry Conditions")
reEnterOnLongTrend = input.bool(false, "Re-Enter on Long Trend continuation", group="Entry Conditions")

// 📌 2️⃣ Short Trades
allowShortTrades = input.bool(false, "Allow Short Trades?", group="Short Trades")

// 📌 Performance Settings
useProfitTarget  = input.bool(false, "Use Profit Target?", group="Performance Settings")
profitTargetRR   = input.float(2.0, "Profit Target (Risk-Reward Ratio)", group="Performance Settings")


// 📌 4️⃣ Dynamic TP/SL (Each Setting with Its Parameters Directly Below)
useATRStopTP    = input.bool(false, "Use ATR-Based Stop-Loss & Take-Profit?", group="Dynamic TP/SL")
atrLength       = input.int(14, "ATR Length", group="Dynamic TP/SL")
atrMultiplier   = input.float(1.5, "Stop-Loss ATR Multiplier", group="Dynamic TP/SL")
profitATRMultiplier = input.float(2.5, "Profit Target ATR Multiplier", group="Dynamic TP/SL")

useTrailingStop = input.bool(false, "Use ATR Trailing Stop?", group="Dynamic TP/SL")
trailStopMultiplier = input.float(1.5, "Trailing Stop ATR Multiplier", group="Dynamic TP/SL")

useBreakEven    = input.bool(false, "Use Break-Even Stop-Loss?", group="Dynamic TP/SL")
breakEvenRR     = input.float(1.5, "Move SL to Break-Even After RR", group="Dynamic TP/SL")

useTrendExit    = input.bool(false, "Use Trend-Based Take Profit (EMA Exit)?", group="Dynamic TP/SL")
emaExitLength   = input.int(9, "EMA Exit Length", group="Dynamic TP/SL")

// 📌 Debug Options
showZlemaDebug = input.bool(false, "Show ZLEMA Trend Debug?", group="Debug")




// ============================================================
// === 1️⃣ CALCULATIONS (Indicators, Trend, ATR, Stop/TP) ===
// ============================================================
src        = close
lag        = math.floor((length - 1) / 2)
zlema      = ta.ema(src + (src - src[lag]), length)
volatility = ta.highest(ta.atr(length), length * 3) * mult

var trend  = 0
if ta.crossover(close, zlema + volatility)
    trend := 1
if ta.crossunder(close, zlema - volatility)
    trend := -1

atrValue = ta.atr(atrLength)
emaExit  = ta.ema(close, emaExitLength)

var float stopLossLongLevel = na
var float profitTargetLongLevel = na
var float stopLossShortLevel = na
var float profitTargetShortLevel = na

var int lastEntryBarIndex = na
var float lastEntryPrice = na

// ✅ Corrected ZLEMA DownTrend Logic: Ensure ZLEMA has decreased for 5 consecutive bars
// ✅ ZLEMA Increasing for 5 Bars → Bullish Trend (Green Triangle Up at the Bottom)
zlemaUpTrend = zlema > zlema[1] and zlema[1] > zlema[2] and zlema[2] > zlema[3] and zlema[3] > zlema[4]

// ✅ ZLEMA Decreasing for 5 Bars → Bearish Trend (Red Triangle Down at the Top)
zlemaDownTrend = zlema < zlema[1] and zlema[1] < zlema[2] and zlema[2] < zlema[3] and zlema[3] < zlema[4]

if ta.crossover(trend, 0) // Long Entry
    stopLossLongLevel := useATRStopTP ? close - (atrValue * atrMultiplier) : zlema - volatility
    profitTargetLongLevel := useProfitTarget ? (close + ((close - stopLossLongLevel) * profitTargetRR)) : na

if ta.crossunder(trend, 0) // Short Entry
    stopLossShortLevel := useATRStopTP ? close + (atrValue * atrMultiplier) : zlema + volatility
    profitTargetShortLevel := useProfitTarget ? (close - ((stopLossShortLevel - close) * profitTargetRR)) : na

// ATR-Based Stop-Loss Levels for Trade Exits
var float atrStopLossLong = na
var float atrStopLossShort = na

if useATRStopTP
    if strategy.position_size > 0  // Long Position
        atrStopLossLong := na(atrStopLossLong) or strategy.position_size[1] == 0 ? close - (atrValue * atrMultiplier) : math.max(nz(atrStopLossLong[1]), close - (atrValue * atrMultiplier))  // Prevents SL from decreasing

    if strategy.position_size < 0  // Short Position
        atrStopLossShort := na(atrStopLossShort) or strategy.position_size[1] == 0 ? close + (atrValue * atrMultiplier) : math.min(nz(atrStopLossShort[1]), close + (atrValue * atrMultiplier))  // Prevents SL from increasing

// ATR-Based Take-Profit Levels
var float atrTakeProfitLong = na
var float atrTakeProfitShort = na

if useATRStopTP
    if strategy.position_size > 0  // Long Position
        atrTakeProfitLong := strategy.position_avg_price + (atrValue * profitATRMultiplier)  // Dynamic TP Based on ATR

    if strategy.position_size < 0  // Short Position
        atrTakeProfitShort := strategy.position_avg_price - (atrValue * profitATRMultiplier)  // Dynamic TP Based on ATR


// ATR Trailing Stop Levels for Trade Exits and Visualization
var float trailStopLongLine = na
var float trailStopShortLine = na

if useTrailingStop
    if strategy.position_size > 0  // Long Position
        trailStopLongLine := na(trailStopLongLine) or strategy.position_size[1] == 0 ? close - (atrValue * trailStopMultiplier) : 
                               math.max(nz(trailStopLongLine[1]), close - (atrValue * trailStopMultiplier))

    if strategy.position_size < 0  // Short Position
        trailStopShortLine := na(trailStopShortLine) or strategy.position_size[1] == 0 ? close + (atrValue * trailStopMultiplier) : 
                               math.min(nz(trailStopShortLine[1]), close + (atrValue * trailStopMultiplier))

// ============================================================
// === 2️⃣ ENTRY & EXIT LOGIC (Conditions for Trading) ===
// ============================================================


// ✅ Entry Conditions for Long Trades
longCondition = ta.crossover(trend, 0) and close > zlema + volatility 
canEnterLong = strategy.position_size == 0 or strategy.position_size[1] < 0  // Allows long entry right after short exit

if useZlemaTrendConfirm
    longCondition := longCondition and zlemaUpTrend  // Ensure ZLEMA Uptrend is true for long entries

// 🔥 Enforce that `longCondition` CANNOT be true if `zlemaUpTrend` is false
if useZlemaTrendConfirm and not zlemaUpTrend
    longCondition := false

// ✅ Entry Conditions for Short Trades
shortCondition = allowShortTrades and ta.crossunder(trend, 0) and close < zlema - volatility
canEnterShort = strategy.position_size == 0 or strategy.position_size[1] > 0  // Allows short entry right after long exit

if useZlemaTrendConfirm
    shortCondition := shortCondition and zlemaDownTrend  // Ensure ZLEMA Downtrend is true for short entries

// ✅ Long Re-Entry Condition: ZLEMA is green, position is flat, price closed below and now above ZLEMA
reEntryLongCondition = reEnterOnLongTrend and
     trend == 1 and
     trend[1] == 1 and  // ✅ Previous bar must also be in bullish trend (prevents triggering on trend change)
     strategy.position_size == 0 and
     close[1] < zlema[1] and
     close > zlema 


// ✅ Debugging: Display `longCondition` and `zlemaUpTrend` values only if the checkbox is checked
if showZlemaDebug and ta.crossover(trend, 0)
    label.new(x=bar_index, y=low, 
              text="LongCondition: " + str.tostring(longCondition) + 
                   "\nZLEMA UpTrend: " + str.tostring(zlemaUpTrend),
              color=color.white, textcolor=color.black, size=size.small, style=label.style_label_down)



// ============================================================
// === 3️⃣ TRADE EXECUTIONS (Entries, ATR SL/TP, Trailing Stop, Trend Exit) ===
// ============================================================

// 📌 Entry Conditions
if (canEnterLong and longCondition) or reEntryLongCondition
    lastEntryBarIndex := bar_index
    lastEntryPrice := close
    
    // 🛠️ Reset all SL/TP levels on Long Entry or Re-Entry
    if reEntryLongCondition
        // Trend-Based SL/TP
        stopLossLongLevel := useATRStopTP ? na : zlema - volatility
        profitTargetLongLevel := useProfitTarget and not useATRStopTP ? (close + ((close - stopLossLongLevel) * profitTargetRR)) : na

        // ATR-Based SL/TP
        atrStopLossLong := useATRStopTP ? close - (atrValue * atrMultiplier) : na
        atrTakeProfitLong := useATRStopTP ? close + (atrValue * profitATRMultiplier) : na

        // Trailing Stop
        trailStopLongLine := useTrailingStop ? close - (atrValue * trailStopMultiplier) : na

    strategy.entry(id="Long", direction=strategy.long, comment=reEntryLongCondition ? "Re-Entry Long" : "Bullish Trend Change")


if canEnterShort and shortCondition
    lastEntryBarIndex := bar_index
    lastEntryPrice := close
    strategy.entry(id="Short", direction=strategy.short, comment="Bearish Trend Change")


// 📌 ATR-Based Stop-Loss Exits (Ensures SL Always Triggers Correctly)
if useATRStopTP and strategy.position_size > 0
    if low <= atrStopLossLong
        strategy.close("Long", comment="ATR SL Hit - Long")

if useATRStopTP and strategy.position_size < 0
    if high >= atrStopLossShort
        strategy.close("Short", comment="ATR SL Hit - Short")

// 📌 ATR-Based Stop-Loss & Take-Profit Exits (Ensures TP Always Executes)
if useATRStopTP and strategy.position_size > 0 and high >= atrTakeProfitLong
    strategy.close("Long", comment="ATR TP Hit - Long")

if useATRStopTP and strategy.position_size < 0 and low <= atrTakeProfitShort
    strategy.close("Short", comment="ATR TP Hit - Short")


// 📌 Profit Target Exits (Ensures TP Always Executes Independently)
if useProfitTarget and strategy.position_size > 0 and high >= profitTargetLongLevel
    strategy.close("Long", comment="Profit Target Hit - Long")

if useProfitTarget and strategy.position_size < 0 and low <= profitTargetShortLevel
    strategy.close("Short", comment="Profit Target Hit - Short")

// 📌 Stop-Loss for Profit Target Trades (Ensures Stop-Loss Works with TP)
if useProfitTarget and strategy.position_size > 0 and low <= stopLossLongLevel
    strategy.close("Long", comment="Stop-Loss Hit - Long")

if useProfitTarget and strategy.position_size < 0 and high >= stopLossShortLevel
    strategy.close("Short", comment="Stop-Loss Hit - Short")

// 📌 ATR Trailing Stop Loss (Ensures It Works Alongside Other Exits)
if useTrailingStop and strategy.position_size > 0 and low <= trailStopLongLine
    strategy.close("Long", comment="Trailing Stop Hit - Long")

if useTrailingStop and strategy.position_size < 0 and high >= trailStopShortLine
    strategy.close("Short", comment="Trailing Stop Hit - Short")

// 📌 Trend-Based Exit (Closes Position When Trend Reverses)
if strategy.position_size > 0 and ta.crossunder(trend, 0)
    strategy.close("Long", comment="Trend Change to Bearish")

if strategy.position_size < 0 and ta.crossover(trend, 0)
    strategy.close("Short", comment="Trend Change to Bullish")

// 📌 Break-Even Stop-Loss (Adjusts Stop to Entry Price at Set Risk-Reward Ratio)
if useBreakEven and strategy.position_size > 0 and high >= strategy.position_avg_price + (strategy.position_avg_price - atrStopLossLong) * breakEvenRR
    atrStopLossLong := strategy.position_avg_price

if useBreakEven and strategy.position_size < 0 and low <= strategy.position_avg_price - (atrStopLossShort - strategy.position_avg_price) * breakEvenRR
    atrStopLossShort := strategy.position_avg_price

// 📌 EMA Exit (Closes Position if Price Crosses EMA)
if useTrendExit and strategy.position_size > 0 and low < emaExit
    strategy.close("Long", comment="Exit on EMA")

if useTrendExit and strategy.position_size < 0 and high > emaExit
    strategy.close("Short", comment="Exit on EMA")



// ============================================================
// === 4️⃣ VISUALIZATIONS (Trend Shading, Stop-Loss, TP, ATR TS) ===
// ============================================================

// 🟢🔴 Restore Bullish/Bearish Trend Shading
zlemaColor = trend == 1 ? color.new(#00ffbb, 70) : color.new(#ff1100, 70)
m = plot(series=zlema, title="Zero Lag Basis", linewidth=2, color=zlemaColor)

upper = plot(zlema + volatility, style=plot.style_linebr, color=color.new(#ff1100, 90), title="Upper Deviation Band")
lower = plot(zlema - volatility, style=plot.style_linebr, color=color.new(#00ffbb, 90), title="Lower Deviation Band")

fill(plot1=m, plot2=upper, color=(trend == -1 ? color.new(#ff1100, 80) : na), title="Bearish Fill")
fill(plot1=m, plot2=lower, color=(trend == 1 ? color.new(#00ffbb, 80) : na), title="Bullish Fill")

// ✅ Plot a lime green TriangleUp at the bottom when ZLEMA has been going UP for 5 bars
plotshape(series=zlemaUpTrend ? low - ta.atr(5) * 0.5 : na, 
          location=location.bottom, style=shape.triangleup, 
          color=color.lime, title="ZLEMA Uptrend Detected")

// ✅ Plot a red TriangleDown at the top when ZLEMA has been going DOWN for 5 bars
plotshape(series=zlemaDownTrend ? high + ta.atr(5) * 0.5 : na, 
          location=location.top, style=shape.triangledown, 
          color=color.red, title="ZLEMA Downtrend Detected")

// 🔴 Default Stop-Loss Lines (Red) - Only Show If ATR SL/TP Is Not Used
plot(series=(not useATRStopTP and strategy.position_size > 0) ? stopLossLongLevel : na, 
     style=plot.style_linebr, color=color.red, linewidth=2, title="Trend Stop-Loss - Long")

plot(series=(not useATRStopTP and strategy.position_size < 0) ? stopLossShortLevel : na, 
     style=plot.style_linebr, color=color.red, linewidth=2, title="Trend Stop-Loss - Short")

// 🟠 ATR Trailing Stop Loss Line (Thin Orange Line) - Only Draw When Checkbox is Checked
plot(series=(useTrailingStop and strategy.position_size > 0) ? trailStopLongLine : na, 
     style=plot.style_linebr, color=color.new(color.orange, 70), linewidth=1, title="ATR Trailing Stop - Long")

plot(series=(useTrailingStop and strategy.position_size < 0) ? trailStopShortLine : na, 
     style=plot.style_linebr, color=color.new(color.orange, 70), linewidth=1, title="ATR Trailing Stop - Short")

// ✅ ATR-Based Stop-Loss Visualization (Ensures Line Stays Until Trade Closes)
plot(series=(useATRStopTP and strategy.position_size > 0) ? atrStopLossLong : na, 
     style=plot.style_linebr, color=color.new(color.red, 50), linewidth=2, title="ATR-Based Stop-Loss - Long")

plot(series=(useATRStopTP and strategy.position_size < 0) ? atrStopLossShort : na, 
     style=plot.style_linebr, color=color.new(color.red, 50), linewidth=2, title="ATR-Based Stop-Loss - Short")

// ✅ ATR-Based Take-Profit Visualization (Ensures Line Stays Until Trade Closes)
plot(series=(useATRStopTP and strategy.position_size > 0) ? atrTakeProfitLong : na, 
     style=plot.style_linebr, color=color.new(color.green, 50), linewidth=2, title="ATR-Based Take-Profit - Long")

plot(series=(useATRStopTP and strategy.position_size < 0) ? atrTakeProfitShort : na, 
     style=plot.style_linebr, color=color.new(color.green, 50), linewidth=2, title="ATR-Based Take-Profit - Short")

// ✅ Standard Profit Target Visualization (Only Active if ATR SL/TP is NOT Used)
plot(series=(useProfitTarget and not useATRStopTP and strategy.position_size > 0) ? profitTargetLongLevel : na, 
     style=plot.style_linebr, color=color.green, linewidth=2, title="Profit Target - Long")

plot(series=(useProfitTarget and not useATRStopTP and strategy.position_size < 0) ? profitTargetShortLevel : na, 
     style=plot.style_linebr, color=color.green, linewidth=2, title="Profit Target - Short")

// === 📋 FLOATING TABLE: STRATEGY PERFORMANCE & SETTINGS ===

// === Track first and last trade times ===
var int firstTradeTime = na
var int lastTradeTime = na

if strategy.opentrades > 0 and na(firstTradeTime)
    firstTradeTime := time

if strategy.closedtrades > 0
    lastTradeTime := time

// === Format trade date strings safely ===
firstDateStr = "N/A"
lastDateStr  = "N/A"

if not na(firstTradeTime)
    firstDateStr := str.tostring(month(firstTradeTime)) + "/" + str.tostring(dayofmonth(firstTradeTime)) + "/" + str.tostring(year(firstTradeTime) % 100)

if not na(lastTradeTime)
    lastDateStr := str.tostring(month(lastTradeTime)) + "/" + str.tostring(dayofmonth(lastTradeTime)) + "/" + str.tostring(year(lastTradeTime) % 100)




相关推荐