볼륨 반전 추세 포착 전략

SMA ATR VOLUME ETH RTH TP SL
생성 날짜: 2025-05-13 10:39:29 마지막으로 수정됨: 2025-05-13 10:39:29
복사: 1 클릭수: 346
avatar of ianzeng123 ianzeng123
2
집중하다
319
수행원

볼륨 반전 추세 포착 전략 볼륨 반전 추세 포착 전략

전략 개요

거래량 반전 트렌드 캡처 전략은 비정상적인 거래량과 가격 행동을 기반으로 시장의 방향 반전이 일어날 수 있는 중요한 시점을 식별하기 위한 양적 거래 방법이다. 이 전략의 핵심은 거래량이 평균보다 훨씬 높은 거래량을 가진 K 라인을 찾아내고 거래량이 감소하는 것을 확인했을 때 이전 트렌드 방향에 따라 반대 거래 결정을 내리는 것이다.

전략 원칙

이 전략의 핵심 원리는 시장의 비정상적인 거래량 후의 트렌드 반전 현상을 기반으로 한다. 구체적인 동작 논리는 다음과 같다:

  1. 비정상적인 거래량을 식별합니다.시스템: 시스템 검사는 전 K 라인이 평균보다 상당히 높은 거래량을 가지고 있는지 여부를 확인합니다. 일반적인 거래 시간 동안 (RTH), 거래량은 최근 평균 거래량보다 3 배 이상으로 필요합니다 (조정 가능합니다); 종전 후 또는 특수 시간 동안 (ETH), 5 배 이상으로 필요합니다. 평균 거래량 계산은 자동으로 RTH 경계 시간, 종전 후 4-6 시점 및 일요일 전 종전 시간을 제외합니다.

  2. 거래량 감소 확인: 현재 K 라인의 거래량은 이전 K 라인보다 낮아야 하며, 이는 대량 거래가 종료되었다는 것을 나타냅니다.

  3. 트렌드 방향: 비정상적인 거래량 K선 전의 종결 가격과 SMA (단순 이동 평균) 의 관계를 비교하여 트렌드 방향을 결정한다.

  4. 역전 진입 신호

    • 다중 신호: 비정상적인 거래량이 K선 이전에 하향 트렌드 ((SMA보다 낮은 종결 가격), 그리고 현재 K선 거래량이 감소한다。
    • 공백 신호: 비정상적인 거래량이 K선 이전에 포지션 트렌드 ((SMA보다 높은 종결 가격), 그리고 현재 K선 거래량이 감소한다。
  5. 입시 실행

    • 더 많이: K 라인의 최소 가격으로 제한 가격을 설정하십시오.
    • 공백 (空置): K선에서 가장 높은 가격으로 한정판매권을 설정한다.
  6. 위험 관리: 다양한 품종의 특성에 따라, 시스템은 두 가지의 중지/정지 설정을 제공합니다:

    • 특정 품종에 대해서는 ((NQ와 같은): 고정 점수 설정을 사용하여 스톱 손실 및 스톱
    • 다른 품종: ATR 기반의 동적 중지/정지, 또는 고정 점수를 사용하는 것을 선택할 수 있다.
  7. 시간 필터전략은 선택적으로 RTH 상반기 15분 거래 신호를 필터링하고, 상반기 이후의 상장 시간 (오후 4-6시) 과 일요일 상장 전의 신호를 필터링합니다.

전략적 이점

  1. 중요한 전환점을 포착하는 것이 전략은 비정상적인 거래량과 함께 발생하는 시장 전환점을 포착하는 데 초점을 맞추고 있습니다. 이 지점은 일반적으로 시장의 감정에 대한 눈에 띄는 변화를 나타내고, 더 높은 승률의 거래 기회를 제공합니다.

  2. 정확한 입구 지점: 제한 가격 단위를 사용하여 비정상적인 거래량 K 선의 고점/저점 입시를 통해 기술적으로 중요한 가격 수준에서 거래하는 것을 보장하고 입시의 정확도를 높인다.

  3. 적응의 양을 알아낼 수 있습니다.: 전략 상시 거래 시간에 따라 비정상적인 거래량을 결정하는 기준을 동적으로 조정하여 실제 시장 상황에 더 적합합니다.

  4. 유연한 위험 관리: 고정 점수 및 ATR에 기반한 스톱/스트롭 옵션을 제공하며, 다양한 품종의 특성 및 변동성에 따라 개인화 설정이 가능합니다.

  5. 지능형 시간 필터: 저 유동성 및 불안정한 거래 시기를 자동으로 식별하고 필터링하여 시장 개시 및 폐쇄 근처에서 쉽게 발생하는 가짜 신호를 피하십시오.

  6. 명확한 시각적 피드백전략: 전략은 K선, 트렌드 SMA선, 스톱로드, 스톱 평준을 포함한 차트 상의 직관적인 시각적 지시를 제공하여 거래자의 모니터링과 분석을 용이하게 합니다.

  7. 자동화 실행: 조건이 충족되면, 시스템은 자동으로 제한 주문을 실행하고, 인적 개입을 줄이고 거래 규율을 유지합니다.

전략적 위험

  1. 가짜 침입 위험: 비정상적인 거래량은 가격이 단기간에 중요한 수준을 돌파하도록 만들 수 있지만, 그 후 빠르게 철회하여 잘못된 신호를 유발할 수 있습니다. 이 위험을 완화하기 위해 RSI 오버 바이 / 오버 셀 확인 또는 돌파 지속 시간 요구 사항과 같은 확인 지표를 추가하는 것이 고려 될 수 있습니다.

  2. 뉴스가 주도하는 사건의 영향주요 경제 데이터 또는 회사 발표가 비정상적인 거래량을 유발할 수 있지만, 이러한 반응은 즉각적인 반전보다는 장기간 지속됩니다. 중요한 경제 데이터가 발표되기 전과 후에 전략을 중단하거나 필터링 조건을 추가하는 것이 좋습니다.

  3. 시장 환경의 변화 위험: 강한 트렌드 시장에서 역행 거래는 지속적인 불리한 가격 움직임을 겪을 수 있다. 강한 트렌드 환경에서 역행을 피하기 위해 장기적인 트렌드 필터를 추가하는 것을 고려할 수 있다.

  4. 한정 가격 표가 거래되지 않은 위험: 가격이 다음 K 라인에서 설정된 제한 가격 수준에 도달하지 않으면 거래 신호가 무효가 될 수 있다. 최대 유효 기간을 설정하는 것을 고려할 수 있으며, 특정 조건에서 시장 가격으로 전환할 수 있다.

  5. 낮은 유동성 위험: 전략에 시간 필터 기능이 포함되어 있음에도 불구하고, 특정 품종은 특정 시간에 유동성이 부족할 수 있습니다. 거래 품종의 특성에 따라 거래 시간 제한을 조정하는 것이 좋습니다.

  6. 매개변수 최적화 위험과잉 최적화 전략의 매개 변수는 역사적 데이터에 과합되어서 미래의 성능이 좋지 않을 수 있다. 매개 변수는 합리적인 범위 내에서 보장되어야 하며, 샘플 외 테스트를 통해 전략의 안정성을 검증해야 한다.

전략 최적화 방향

  1. 다중 시간 주기 확인: 더 높은 시간 주기의 트렌드 필터를 추가하여 더 큰 트렌드 방향에서 더 높은 승률을 보장합니다. 예를 들어, 일계 트렌드 방향을 확인할 수 있으며, 일계 트렌드와 일치하는 경우에만 출전합니다.

  2. 거래량 및 품질 평가순량 에너지 크기에 더하여 거래량 가중 평균 가격 (VWAP) 오차와 같은 거래량 품질 평가를 추가하여 큰 거래량 뒤에있는 시장 행동을 더 잘 이해할 수 있습니다.

  3. 역동적 상쇄 전략: 변동률에 기반한 동적 스톱을 구현하고, 거래가 유리한 방향으로 진행됨에 따라 자동으로 스톱 포지션을 조정하여 수익의 일부를 잠금합니다. 예를 들어, 추적 스톱을 사용할 수 있으며, 또는 중요한 수준을 돌파 한 후 스톱을 비용으로 이동할 수 있습니다.

  4. 다종 관련 필터관련 품종에 대해 (주식 지수 선물과 현금, 금과 은 등) 관련 품종의 확인 지표를 추가하면 신호 품질이 향상됩니다. 여러 관련 품종이 동시에 비정상적인 거래량과 가격 행동을 볼 때 신호가 더 신뢰할 수 있습니다.

  5. 기계 학습 최적화: 기계 학습 알고리즘을 통해 역사 데이터에서 가장 성공적인 비정상적인 거래량 패턴 특성을 분석하고, 진입 조건과 매개 변수를 동적으로 조정한다. 예를 들어, 의사 결정 나무 또는 무작위 숲을 사용하여 주어진 비정상적인 거래량 특성에 따른 최적의 행동을 예측할 수 있다.

  6. 변동률 조정: 시장의 현재 변동률 상태에 따라 비정상적인 거래량 판단 기준과 중지/정지 수준을 조정한다. 높은 변동률 환경에서 비정상적인 양을 높이면 정지값을 판단하고, 손실 거리를 줄일 수 있다. 낮은 변동률 환경에서 반대로한다.

  7. 기본 필터를 추가합니다.: 주요 경제 자료가 발표되는 날이나 분기금융 보고서의 계절적 조정 전략 파라미터 또는 거래 중단, 뉴스페이지 방해로 인한 잘못된 신호를 피하기 위해.

요약하다

거래량 반전 트렌드 캡처 전략은 거래량과 가격 행동에 초점을 맞춘 정량 거래 시스템으로, 비정상적인 거래량 후의 시장 정서 변화를 식별하여 잠재적인 반전을 포착합니다. 이 전략은 기술적으로 명확하게 입출장 조건과 위험 관리 규칙을 정의하고, 시장의 저품질 시기를 피하기 위해 지능적인 시간 필터링 장치를 포함합니다.

전략의 핵심 장점은 시장의 “중도 형태”를 정확하게 포착하는 데 있습니다. 시장 참가자가 대량으로 유입되고 그 후 철수 할 때, 단기 반전 기회가 종종 발생합니다. 이 전략은 중요한 가격 수준에서 가격 제한 단위를 정확하게 설정하고 합리적인 스톱 스톱 관리와 함께 규율된 거래 방법을 제공합니다.

그러나, 사용자는 전략이 강한 추세 시장에서 잠재적인 위험과 뉴스페이스 이벤트에 대한 민감성을 주의해야 합니다. 이 전략은 다중 시간 주기 확인, 동적으로 매개 변수 조정 및 위험 관리 메커니즘을 강화함으로써 성능의 안정성과 적응성을 더욱 최적화 할 수 있습니다.

전체적으로 거래량 반전 트렌드 캡처 전략은 거래자에게 시장 행동과 심리학 원칙에 기반한 거래 시스템을 제공하며 특히 변동성있는 시장과 간격의 변동 상황에 적합합니다. 합리적인 설정과 지속적인 최적화를 통해이 전략은 거래 포트폴리오에서 효과적인 도구가 될 수 있습니다.

전략 소스 코드
/*backtest
start: 2024-05-13 00:00:00
end: 2025-05-11 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
// Strategy Title Reflects Latest Logic
strategy(title="Middle Finger Trading Strategy",
         shorttitle="Middle_Finger",
         overlay=true,
         pyramiding=0, // Only one entry at a time
         default_qty_type=strategy.percent_of_equity,
         default_qty_value=1, // Trade 1% of equity
         commission_value=0.04, // Example commission (adjust as needed)
         commission_type=strategy.commission.percent,
         initial_capital = 10000, // Example starting capital
         process_orders_on_close=false // Important for limit orders to potentially fill intra-bar
         )

// --- Inputs ---

// Volume Settings Group
grp_vol = "Volume Settings"
float rthHugeVolMultiplier = input.float(3.0, title="1. RTH Huge Vol. Multiplier (> Avg)", minval=1.1, step=0.1, group=grp_vol, tooltip="Multiplier for core RTH (9:45-15:44 ET)")
float ethHugeVolMultiplier = input.float(5.0, title="2. ETH/Excluded Huge Vol. Multiplier (> Avg)", minval=1.1, step=0.1, group=grp_vol, tooltip="Multiplier for ETH and first/last 15min RTH (default 5x)")
int   volLookback         = input.int(20, title="3. Volume SMA Lookback", minval=1, group=grp_vol, tooltip="Lookback for calculating the filtered average volume (Used ONLY for identifying the HUGE spike)")
// Removed normalVolMultiplier as it's no longer used for entry confirmation

// Trend Settings Group
grp_trend = "Trend Settings"
int   trendLookback       = input.int(20, title="1. Trend SMA Lookback", minval=2, group=grp_trend, tooltip="Lookback period for the Simple Moving Average used to determine the trend before the spike")

// Risk Management Group
grp_risk = "Risk Management (SL/TP)"
string nqTargetTickerId   = input.string("CME:NQ1!", title="1. Target Ticker ID for Fixed NQ Points", group=grp_risk, tooltip="Specify the exact Ticker ID (e.g., CME:NQ1!, TVC:NDX) for fixed SL/TP. Found in Symbol Info.")
float nqFixedStopPoints   = input.float(20.0, title="2. Fixed SL Points (for Target Ticker)", group=grp_risk, minval=0.1, step=0.1)
float nqFixedTpPoints     = input.float(50.0, title="3. Fixed TP Points (for Target Ticker)", group=grp_risk, minval=0.1, step=0.1)

// General SL/TP Settings (used if NOT the target ticker)
bool  useAtrStops         = input.bool(true, title="4. Use ATR for SL/TP (Other Tickers)?", group=grp_risk)
int   atrLookback         = input.int(14, title="5. ATR Lookback", group=grp_risk, inline="atr_other")
float atrStopMultiplier   = input.float(2.0, title="6. ATR SL Multiplier", group=grp_risk, inline="atr_other", minval=0.1, step=0.1)
float atrTpMultiplier     = input.float(4.0, title="7. ATR TP Multiplier", group=grp_risk, inline="atr_other", minval=0.1, step=0.1)
float fixedStopPoints     = input.float(100.0, title="6. Fixed SL Points (Other Tickers)", group=grp_risk, inline="fixed_other", minval=1)
float fixedTpPoints       = input.float(200.0, title="7. Fixed TP Points (Other Tickers)", group=grp_risk, inline="fixed_other", minval=1)

// Time Filter Settings Group
grp_time = "Time Filter (ET)"
bool  enableEntryFilterRthEdges = input.bool(true, title="1. Filter Entries First/Last 15 Min RTH (ET)?", group=grp_time, tooltip="If checked, ignores entries from 9:30-9:44 ET and 15:45-15:59 ET. Avg Vol calc *always* filters these times, 4-6PM ET, and Sun pre-6PM ET.")
string targetTimezone     = "America/New_York" // Specify Eastern Time zone

// --- Time Calculation Function ---
isTimeInSession(t, tz, sessionString) =>
    not na(time(timeframe.period, sessionString, tz))

// --- Time Context Functions ---
getTimeContext(t, tz) =>
    h = hour(t, tz)
    m = minute(t, tz)
    d = dayofweek(t, tz)

    // Core RTH: 9:45 AM to 15:44 PM ET (Mon-Fri)
    bool isCoreRTH = d >= dayofweek.monday and d <= dayofweek.friday and
       ((h == 9 and m >= 45) or (h >= 10 and h <= 14) or (h == 15 and m <= 44))

    // Excluded RTH Edges: 9:30-9:44 ET and 15:45-15:59 ET (Mon-Fri)
    bool isExcludedRTH = d >= dayofweek.monday and d <= dayofweek.friday and
       ((h == 9 and m >= 30 and m <= 44) or (h == 15 and m >= 45))

    // After Hours Closed: 4:00 PM to 5:59 PM ET (Mon-Fri)
    bool isAfterHoursClosed = d >= dayofweek.monday and d <= dayofweek.friday and
       (h >= 16 and h < 18)

    // Sunday Pre-Market: Sunday before 6:00 PM ET
    bool isSundayPreMarket = d == dayofweek.sunday and h < 18

    // Combine ALL periods where activity should be ignored or volume excluded from avg
    bool isExcludedPeriod = isExcludedRTH or isAfterHoursClosed or isSundayPreMarket

    [isCoreRTH, isExcludedRTH, isAfterHoursClosed, isSundayPreMarket, isExcludedPeriod]

// --- Get Time Context for Current and Previous Bar ---
[isCurrentBarCoreRTH, isCurrentBarExcludedRTH, isCurrentBarAfterHoursClosed, isCurrentBarSundayPreMarket, isCurrentBarExcludedPeriod] = getTimeContext(time, targetTimezone)
[isPreviousBarCoreRTH, isPreviousBarExcludedRTH, isPreviousBarAfterHoursClosed, isPreviousBarSundayPreMarket, isPreviousBarExcludedPeriod] = getTimeContext(time[1], targetTimezone)

// --- Calculations ---

// Volume Averaging: Exclude RTH edges, 4-6 PM ET, and Sunday Pre-6 PM ET ALWAYS
// This average is *only* used to define the huge volume spike threshold
bool excludeCurrentVolFromAvg = isCurrentBarExcludedPeriod
float volumeForAvgCalc = excludeCurrentVolFromAvg ? na : volume
float avgVolume = ta.sma(volumeForAvgCalc, volLookback)

// Dynamic Huge Volume Multiplier: Based on *previous* bar's time (Core RTH or not)
float activeHugeVolMultiplier = isPreviousBarCoreRTH ? rthHugeVolMultiplier : ethHugeVolMultiplier
// Use avgVolume[1] as current avgVolume excludes current bar, and we compare previous volume to avg *before* it
float hugeVolThreshold   = nz(avgVolume[1]) * activeHugeVolMultiplier

// --- MODIFIED Volume Conditions ---
// 1. Check if the *previous* bar had huge volume compared to its preceding average
bool isHugeVolumePrevBar = volume[1] > hugeVolThreshold and hugeVolThreshold > 0
// 2. Check if the *current* bar's volume is simply lower than the previous (huge) bar's volume
bool isVolumeLowerThanSpike = volume < volume[1]

// Trend Condition
float priceSma = ta.sma(close, trendLookback)
// Ensure trend condition uses close[2] vs sma[2] (trend state *before* the spike bar)
bool isBullishTrendBeforeSpike = close[2] > nz(priceSma[2])
bool isBearishTrendBeforeSpike = close[2] < nz(priceSma[2])

// --- Entry Time Filtering ---
// Always filter After Hours Closed and Sunday Pre-Market.
// Optionally filter RTH Edges based on input.
bool shouldFilterRthEdges = enableEntryFilterRthEdges and isCurrentBarExcludedRTH
bool isIgnoreEntryTime = shouldFilterRthEdges or isCurrentBarAfterHoursClosed or isCurrentBarSundayPreMarket

// --- MODIFIED Base Conditions ---
// Uses the simplified `isVolumeLowerThanSpike` check
bool baseLongCondition = isBearishTrendBeforeSpike and isHugeVolumePrevBar and isVolumeLowerThanSpike
bool baseShortCondition = isBullishTrendBeforeSpike and isHugeVolumePrevBar and isVolumeLowerThanSpike

// Final Conditions (Apply Time Filter)
bool finalLongCondition = baseLongCondition and not isIgnoreEntryTime
bool finalShortCondition = baseShortCondition and not isIgnoreEntryTime

// --- Stop Loss & Take Profit Calculation (Conditional Logic) ---
// This part remains the same
float atrValue = ta.atr(atrLookback)
float tickValue = syminfo.mintick
int stopLossTicks = 100 // Default fallback SL ticks
int takeProfitTicks = 200 // Default fallback TP ticks

// Check if the current symbol matches the target ticker ID
bool isTargetTicker = str.upper(syminfo.tickerid) == str.upper(nqTargetTickerId) // Case-insensitive comparison

if (isTargetTicker and tickValue > 0)
    // --- Target Ticker Logic (e.g., NQ Fixed Points) ---
    float ticksPerPoint = 1.0 / tickValue
    stopLossTicks := math.max(1, math.round(nqFixedStopPoints * ticksPerPoint))
    takeProfitTicks := math.max(1, math.round(nqFixedTpPoints * ticksPerPoint))
else if tickValue > 0 // Use only if tickValue is valid
    // --- Standard Logic (Other Tickers: ATR or Fixed) ---
    float stopLossDistance = useAtrStops ? atrValue * atrStopMultiplier : fixedStopPoints * tickValue
    float takeProfitDistance = useAtrStops ? atrValue * atrTpMultiplier : fixedTpPoints * tickValue

    // Calculate ticks, ensuring it's at least 1 tick
    stopLossTicks := na(stopLossDistance) ? 100 : math.max(1, math.round(stopLossDistance / tickValue))
    takeProfitTicks := na(takeProfitDistance) ? 200 : math.max(1, math.round(takeProfitDistance / tickValue))

// Final check to ensure SL/TP are not na
stopLossTicks := nz(stopLossTicks, 100)
takeProfitTicks := nz(takeProfitTicks, 200)


// --- Strategy Execution ---
// Uses Limit Orders based on previous bar's low/high - Remains the same
float limitEntryPriceLong = low[1]  // Target entry at the low of the huge volume bar
float limitEntryPriceShort = high[1] // Target entry at the high of the huge volume bar

if (finalLongCondition and strategy.position_size == 0)
    strategy.cancel("S") // Cancel any pending short limit order first
    strategy.entry("L", strategy.long, limit = limitEntryPriceLong)
    strategy.exit("L SL/TP", from_entry="L", loss=stopLossTicks, profit=takeProfitTicks)

if (finalShortCondition and strategy.position_size == 0)
    strategy.cancel("L") // Cancel any pending long limit order first
    strategy.entry("S", strategy.short, limit = limitEntryPriceShort)
    strategy.exit("S SL/TP", from_entry="S", loss=stopLossTicks, profit=takeProfitTicks)


// --- Plotting & Visuals ---
plot(avgVolume, title="Filtered Avg Volume", color=color.new(color.blue, 60), style=plot.style_line)
// Removed the plot for the normal volume threshold as it's no longer used

// Highlight huge volume bar (previous bar that triggered the signal)
bgcolor(isHugeVolumePrevBar[1] ? color.new(color.yellow, 85) : na, title="Huge Volume Bar [-1]")

// Highlight bars excluded from volume average calculation
bgcolor(excludeCurrentVolFromAvg ? color.new(color.teal, 90) : na, title="Vol Excluded from Avg Calc")

// Highlight bars where entries are ignored due to time filters
bgcolor(isIgnoreEntryTime and (baseLongCondition or baseShortCondition) ? color.new(color.gray, 75) : na, title="Entry Time Filtered Bar")

// --- MODIFIED Highlight base conditions met ---
// Reflects the updated base conditions using isVolumeLowerThanSpike
bgcolor(baseLongCondition and not isIgnoreEntryTime ? color.new(color.green, 90) : na, title="Base Long Condition Met")
bgcolor(baseShortCondition and not isIgnoreEntryTime ? color.new(color.red, 90) : na, title="Base Short Condition Met")

plot(priceSma, title="Trend SMA", color=color.gray)

// Plot SL/TP levels for visualization - Remains the same
var float entryPrice = na
var float slLevel = na
var float tpLevel = na

if (strategy.opentrades > 0 and strategy.opentrades[1] == 0) // Just entered a trade
    entryPrice := strategy.opentrades.entry_price(0)
    if (strategy.position_size > 0) // Long
        slLevel := entryPrice - stopLossTicks * tickValue
        tpLevel := entryPrice + takeProfitTicks * tickValue
    else // Short
        slLevel := entryPrice + stopLossTicks * tickValue
        tpLevel := entryPrice - takeProfitTicks * tickValue
else if (strategy.opentrades == 0 and strategy.opentrades[1] > 0) // Position closed
    entryPrice := na
    slLevel := na
    tpLevel := na
else if (strategy.opentrades > 0) // Position still open
    entryPrice := strategy.opentrades.entry_price(0)
    if (strategy.position_size > 0) // Long
        slLevel := entryPrice - stopLossTicks * tickValue
        tpLevel := entryPrice + takeProfitTicks * tickValue
    else // Short
        slLevel := entryPrice + stopLossTicks * tickValue
        tpLevel := entryPrice - takeProfitTicks * tickValue

plot(strategy.opentrades > 0 ? slLevel : na, title="Stop Loss Level", color=color.red, style=plot.style_linebr)
plot(strategy.opentrades > 0 ? tpLevel : na, title="Take Profit Level", color=color.green, style=plot.style_linebr)

// Optional Debugging Plots
// plotchar(isHugeVolumePrevBar, "HugeVol[1]", "H", location.bottom, color.yellow, size=size.tiny)
// plotchar(isVolumeLowerThanSpike, "VolLow", "v", location.bottom, color.purple, size=size.tiny) // Changed char
// plotchar(finalLongCondition, "FinalLong", "L", location.top, color.green, size=size.tiny)
// plotchar(finalShortCondition, "FinalShort", "S", location.top, color.red, size=size.tiny)
// plot(finalLongCondition ? limitEntryPriceLong : na, "Long Limit Target", color.lime, style=plot.style_circles, linewidth=2)
// plot(finalShortCondition ? limitEntryPriceShort : na, "Short Limit Target", color.fuchsia, style=plot.style_circles, linewidth=2)