듀얼 타임 프레임 스토캐스틱 오실레이터 차익거래 전략

STOCH KDJ MA RSI VWMA SMA EMA WMA
생성 날짜: 2025-06-18 13:47:35 마지막으로 수정됨: 2025-06-18 13:47:35
복사: 0 클릭수: 318
avatar of ianzeng123 ianzeng123
2
집중하다
319
수행원

듀얼 타임 프레임 스토캐스틱 오실레이터 차익거래 전략 듀얼 타임 프레임 스토캐스틱 오실레이터 차익거래 전략

개요

이중 시간 프레임 무작위 진동 지표 중개 거래 전략은 무작위 진동 지표 (Stochastic Oscillator) 를 기반으로 한 일간 고주파 거래 시스템으로, 이 전략의 핵심은 두 개의 서로 다른 파라미터 세트의 무작위 진동 지표를 사용하여 15 초 시간 프레임에서 거래 신호를 생성하고 확인한다. 주요 논리는 주요 무작위 지표의 %K 라인과 %D 라인의 교차로 잠재적 인 진입 지점을 식별하는 데 사용되며, 부수적인 무작위 지표의 %D 값을 참조하여 시장 상태 필터로 사용하며, 이동 평균선과 시장 시간 필터 조건을 결합하여 다층 확인 메커니즘을 구축하는 거래 시스템을 구축한다. 이 전략에는 고저 모드 식별 기능이 포함되어 있으며, 황소 시장과 곰 시장의 연속 형태를 포착하고, 가짜 신호를 줄이기 위해 여러 위험 제어 파라미터를 설정할 수 있습니다.

전략 원칙

이 전략은 두 개의 무작위적인 진동 지표 시스템을 사용하며, 각각 주요 지표와 참조 지표로 알려져 있다:

  1. 주요 무작위 진동 지표 설정:

    • 시간 프레임:15초
    • K선 길이: 12
    • K선 부드러움:12
    • D선 길이는: 12
  2. 무작위 진동 지표 설정 참조:

    • 시간 프레임:15초
    • K선 길이: 12
    • K선 부드러움:15
    • D선 길이: 30

입구 논리 설계는 세밀하고, 신호의 유효성을 확인하는 여러 계층이 있다:

  • 입학 조건:

    • 주요 지표 %K 선에 %D 선을 통과하고,
    • 참고 지표 %D 값 ≥50 또는 <20, 또는
    • 주요 지표 %K는 참조 지표 %D에 가깝다 (차이율은 0.15 내외)
    • 가격 이동 평균 (MA 필터링이 활성화 된 경우)
    • 거래 시간은 상시 시간 (9:30 AM - 4:00 PM ET) 에 있어야 합니다.
  • 공허 입학 조건:

    • 주요 지표 %K 라인 아래 %D 라인을 통과하고,
    • 참조 지표 %D의 용량 범위 내에 위치하거나, 특정 하단 착용 조건을 충족
    • 가격의 이동 평균 아래
    • 거래시간은 상시시장 시간으로 되어있어야 합니다.

이 경우, 출구 논리는 시간 및 기술 신호의 조합에 기반합니다.

  • 탈퇴 시간:
    • 동부 시간으로 오후 3시 30분 (정규시장시간이 끝나기 전)
  • 기술 탈퇴:
    • 다중 상위 위치: 주요 지표 %K 아래 참조 지표 %D
    • 빈 머리 포지션: 주요 지표%K 위에 참조 지표%D를 착용하고 참조 지표%D>20

이 전략은 또한 모형 인식 기능도 포함하고 있습니다.

  • 더 높은 하위점 형태: 현재 상단점의 %K 값이 이전 상단점의 %K 값보다 높다 ((보 지속 형태)
  • 더 낮은 최고점 형태: 현재 하위 침입점의 %K 값이 이전 침입점의 %K 값보다 낮다 ((상승 지속 형태)

전략적 이점

  1. 다단계 인증 메커니즘: 두 개의 서로 다른 구성의 무작위 진동 지표를 통해 상호 확인, 단일 지표에 의해 생성되는 가짜 신호를 줄이고 신호 신뢰성을 향상

  2. 정확한 출입 및 퇴출 규칙전략은 명확한 입출입 조건을 정의하고 거래 결정의 주관성을 제거하여 완전히 체계화된 거래를 실현합니다.

  3. 형상 인식 능력시장의 “높은 하위”와 “낮은 높은” 형태를 식별할 수 있고, 트렌드 지속 기회를 잡을 수 있습니다. 이것은 많은 간단한 전략이 할 수 없는 기능입니다.

  4. 시간 필터상시 시간대에 거래 시간을 제한하여, 상장과 상장 전의 높은 변동과 낮은 유동성의 시기를 피하여, 슬라이드 포인트와 비용을 줄입니다.

  5. 이동 평균 필터선택 가능한 이동 평균 필터 기능은 트렌드 확인 계층을 추가하여 거래 방향이 전체 트렌드와 일치하도록합니다.

  6. 가격 차이와 용량 차이 변수이 전략은 가격 변동의 폭과 지표 차이의 범위를 제어하는 여러 가지 파라미터를 도입하여 미세한 변동으로 인한 잡음 신호를 효과적으로 필터링합니다.

  7. 동적 논리 변환: 시스템은 시장상태에 따라 동적으로 조정할 수 있고, 공중에서 공중으로의 전환 조건에 따라 적응력이 강하다.

  8. 전체적인 경보 시스템이 전략은 실시간으로 트랜잭션을 감시하고 실행할 수 있는 풍부한 경보 조건을 포함하고 있습니다.

전략적 위험

  1. 짧은 시간 프레임의 고주파 거래 위험15초 시간 프레임을 사용하는 전략은 과도한 신호를 생성할 수 있으며, 이는 거래의 빈도와 거래 비용을 증가시키고, 시장의 큰 변동이 있을 경우 많은 양의 가짜 신호를 생성할 수 있다.

  2. 손해 방지 장치의 부재: 코드에 명확한 스톱로스 구현이 없으며, 트렌드가 급격히 역전되면 큰 손실 위험에 직면할 수 있습니다. 위험 통제의 부족은 전략의 주요 약점 중 하나입니다.

  3. 매개변수 민감도전략이 사용하는 여러 정확한 매개 변수들 (예: 0.15의 차차 마이너스, 0.1%의 가격 차차 상한 등) 은 서로 다른 시장 조건에 너무 민감할 수 있으며, 자주 조정할 필요가 있다.

  4. 시간적 제약의 기회비용상시 시간에만 거래하는 경우 중요한 상장 전과 상장 후의 기회를 놓칠 수 있습니다. 특히 중요한 뉴스 발표 이후의 시장 반응에서요.

  5. 유동성에 대한 의존: 높은 주파수 전략은 낮은 유동성 시장에서 슬라이드 포인트 문제에 직면할 수 있으며, 실제 실행 가격은 신호 생성 시의 가격과 현저하게 차이가 있을 수 있다.

  6. 기술 지표 지연: 무작위적 변동 지표는 그 자체로 지연성이 있으며, 특히 빠르게 변하는 시장에서 전환점을 적시에 잡지 못할 수 있습니다.

  7. 과도한 적합성의 위험전략 파라미터의 정교한 조정으로 인해 역사적 데이터에 과도한 적합성이 발생할 수 있으며, 미래 시장 환경에서 좋지 않은 성능을 나타낼 수 있습니다.

전략 최적화 방향

  1. 손해 방지 장치가장 중요한 최적화 지점은 지능적인 중지 시스템을 구현하는 것입니다. ATR (평균 실제 변동 범위) 를 기반으로 한 중지 전략을 고려하거나 기술 수준을 사용하여 단일 거래의 최대 손실을 제한하기 위해 중지 지점으로 사용 할 수 있습니다.

  2. 포지션 관리: 시장의 변동성과 계좌의 위험 감수성에 따라 거래 규모를 동적으로 조정합니다. 다양한 신호 강도에서 다양한 포지션配置을 사용하여 자금 사용률과 위험 수익률을 최적화합니다.

  3. 수량 확인: 거래량 지표를 시스템에 통합하여, 중요한 입구 신호가 낮은 거래량 환경에서 신뢰할 수없는 신호를 필터링 할 수있는 충분한 거래량 지원을 받아야합니다.

  4. 다중 지표 통합RSI, MACD 또는 브린 띠와 같은 다른 동력 및 추세 지표와 결합하여 더 포괄적인 시장 관점을 구축하고 시스템의 안정성을 향상시키는 것을 고려하십시오.

  5. 최적화 시간 프레임: 1분 또는 5분과 같은 다양한 기본 시간 프레임을 테스트하여 소음을 줄이면서도 충분한 거래 기회를 유지하여 신호 품질과 수량의 최적의 균형을 찾을 수 있습니다.

  6. 추가된 재검토 통계: 전략의 성능을 보다 과학적으로 평가하기 위해 최대 회수, 셰프 비율, 승률, 손익률 등과 같은 보다 포괄적인 회수 성능 지표를 구현한다.

  7. 적응 변수: 고정된 매개 변수를 시장의 변동성 동력에 따라 조정되는 적응 매개 변수로 변환하여 전략이 다른 시장 환경에 적응할 수 있도록 한다.

  8. 시장 환경 필터링: 시장 환경 필터링 조건으로 VIX (변동률 지수) 또는 유사한 지표를 추가하여 높은 변동성 환경에서 전략 파라미터를 조정하거나 거래를 중단하십시오.

요약하다

이중 시간 프레임 무작위 흔들림 지표 중개 거래 전략은 두 개의 무작위 흔들림 지표, 이동 평균 필터링 및 시간 필터링과 같은 다층 확인 메커니즘을 통해 거래 신호의 신뢰성을 향상시키는 정교하게 설계된 단기 고주파 거래 시스템입니다. 이 전략은 규칙 시장 시간 내에 단기 오버 구매 오버 판매 전환점과 추세 지속 형태를 식별하여 충분한 유동성과 적당한 변동성이있는 시장에 적합합니다.

전략 설계 구조가 완벽함에도 불구하고, 고주파 거래의 고유한 위험과 손실을 막는 등의 핵심 위험 관리 장치의 부족이 남아있다. 전략의 안정성과 장기적인 수익성을 높이기 위해, 전략의 손실을 막는 장치, 포지션 관리 시스템, 거래량 확인 및 다중 지표 통합과 같은 최적화 조치를 추가하는 것이 권장된다. 또한, 고정된 매개 변수를 적응 매개 변수로 변환하고, 전체적인 재측정 통계 추적을 추가하면 전략이 다양한 시장 환경에서 안정적인 성과를 유지하는데 도움이 될 것이다.

이 거래 시스템은 거래자가 이 전략을 깊이 이해하고 지속적으로 최적화하면, 특히 기술 지표에 대한 깊은 이해를 가지고 있고 시시각에 시장을 모니터링 할 수 있는 거래자에게 유용하게 사용될 수 있습니다.

전략 소스 코드
/*backtest
start: 2025-01-01 00:00:00
end: 2025-06-17 00:00:00
period: 4h
basePeriod: 4h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
*/

//@version=6
strategy("Dual TF Stochastic Strategy", overlay=false)

// Input parameters with updated defaults
primaryLen = input.int(12, "Primary Stoch K Length", minval=1)  // Changed from 14 to 12
primarySmooth = input.int(12, "Primary Stoch K Smoothing", minval=1)  // Changed from 3 to 12
primaryDLen = input.int(12, "Primary Stoch D Length", minval=1)  // Changed from 3 to 12
primaryRes = input.timeframe("15S", "Primary Timeframe")  // Changed from "" to "15S"

refLen = input.int(12, "Reference Stoch K Length", minval=1)  // Changed from 14 to 12
refSmooth = input.int(15, "Reference Stoch K Smoothing", minval=1)  // Changed from 3 to 15
refDLen = input.int(30, "Reference Stoch D Length", minval=1)  // Changed from 3 to 30
refRes = input.timeframe("15S", "Reference Timeframe")  // Changed from "D" to "15S"

tolerance = input.float(0.1, "Ref D Tolerance %", minval=0.1, maxval=10.0, step=0.1)  // Changed from 1.0 to 0.1
maxPriceDiff = input.float(0.1, "Maximum Price % Difference", minval=0.1, maxval=5.0, step=0.1)  // Changed from 1.0 to 0.1
closeKThreshold = input.float(0.7, "Close %K Tolerance %", minval=0.1, maxval=10.0, step=0.1)  // Changed from 5.0 to 0.7
minPriceDiffShort = input.float(0.1, "Min Price % Diff for Close %K Short", minval=0.1, maxval=5.0, step=0.1)  // Changed from 0.5 to 0.1
showLabels = input.bool(true, "Show Crossover/Crossunder Labels")

// Time Filters (America/New_York timezone, UTC-4)
is_premarket = hour(time, "America/New_York") < 9
is_postmarket = hour(time, "America/New_York") >= 16
is_regular_hours = hour(time, "America/New_York") >= 9 and hour(time, "America/New_York") < 16
is_exit_time = hour(time, "America/New_York") >= 15 and minute(time, "America/New_York") >= 30  // 3:30 PM ET

// Moving Average Settings
useMAFilter = input.bool(true, "Use Moving Average Filter")
maLength = input.int(200, "Moving Average Length", minval=1)
maType = input.string("SMA", "Moving Average Type", options=["SMA", "EMA", "WMA", "VWMA"])
maTimeframe = input.timeframe("", "Moving Average Timeframe")

// Stochastic Calculations
primaryHighest = ta.highest(high, primaryLen)
primaryLowest = ta.lowest(low, primaryLen)
primaryK_raw = 100 * (close - primaryLowest) / (primaryHighest - primaryLowest)
primaryK = ta.sma(primaryK_raw, primarySmooth)
primaryD = ta.sma(primaryK, primaryDLen)
[primaryK_tf, primaryD_tf] = request.security(syminfo.tickerid, primaryRes, [primaryK, primaryD])

refHighest = ta.highest(high, refLen)
refLowest = ta.lowest(low, refLen)
refK_raw = 100 * (close - refLowest) / (refHighest - refLowest)
refK = ta.sma(refK_raw, refSmooth)
refD = ta.sma(refK, refDLen)
[refK_tf, refD_tf] = request.security(syminfo.tickerid, refRes, [refK, refD])

// Calculate Moving Average
var float ma = na
if useMAFilter
    if maType == "SMA"
        ma := request.security(syminfo.tickerid, maTimeframe, ta.sma(close, maLength))
    else if maType == "EMA"
        ma := request.security(syminfo.tickerid, maTimeframe, ta.ema(close, maLength))
    else if maType == "WMA"
        ma := request.security(syminfo.tickerid, maTimeframe, ta.wma(close, maLength))
    else if maType == "VWMA"
        ma := request.security(syminfo.tickerid, maTimeframe, ta.vwma(close, maLength))

// Price relative to MA
priceAboveMA = not useMAFilter or close > ma
priceBelowMA = not useMAFilter or close < ma

// Crossover Detection and Tracking
crossOver = ta.crossover(primaryK_tf, primaryD_tf)
crossUnder = ta.crossunder(primaryK_tf, primaryD_tf)

// Separate tracking for crossover and crossunder %K and price
var float lastCrossOverK = na
var float lastCrossOverPrice = na
var float currentCrossOverK = na
var float currentCrossOverPrice = na

var float lastCrossUnderK = na
var float lastCrossUnderPrice = na
var float currentCrossUnderK = na
var float currentCrossUnderPrice = na

// Update crossover tracking variables
if crossOver
    lastCrossOverK := nz(currentCrossOverK, primaryK_tf[1])
    lastCrossOverPrice := nz(currentCrossOverPrice, close[1])
    currentCrossOverK := primaryK_tf
    currentCrossOverPrice := close

// Update crossunder tracking variables
if crossUnder
    lastCrossUnderK := nz(currentCrossUnderK, primaryK_tf[1])
    lastCrossUnderPrice := nz(currentCrossUnderPrice, close[1])
    currentCrossUnderK := primaryK_tf
    currentCrossUnderPrice := close

// Calculate differences separately
crossOverPriceDiffPercent = math.abs((currentCrossOverPrice - lastCrossOverPrice) / lastCrossOverPrice * 100)
crossOverKDiffPercent = math.abs((currentCrossOverK - lastCrossOverK) / lastCrossOverK * 100)
crossUnderPriceDiffPercent = math.abs((currentCrossUnderPrice - lastCrossUnderPrice) / lastCrossUnderPrice * 100)
crossUnderKDiffPercent = math.abs((currentCrossUnderK - lastCrossUnderK) / lastCrossUnderK * 100)

isKCloseCrossUnder = crossUnderKDiffPercent <= closeKThreshold and not na(lastCrossUnderK)

// New condition for long entry based on %K and refD_tf difference
kAndRefDDiffClose = crossOver and math.abs(currentCrossOverK - refD_tf) <= 0.15

// Labels for crossover and crossunder (optional)
if showLabels
    if crossOver
        diffKandRefD = math.abs(currentCrossOverK - refD_tf)
        label.new(bar_index, 50, "CrossOver\nDiff K-RefD: " + str.tostring(diffKandRefD, "#.###"), color=color.green, textcolor=color.black, style=label.style_label_up)
    if crossUnder
        diffKandRefD = math.abs(currentCrossUnderK - refD_tf)
        label.new(bar_index, 50, "CrossUnder\nDiff K-RefD: " + str.tostring(diffKandRefD, "#.###"), color=color.red, textcolor=color.black, style=label.style_label_down)

// Entry Conditions
longKCondition = crossOver and (na(lastCrossOverK) or currentCrossOverK > lastCrossOverK)
shortKCondition = crossUnder and (crossUnderPriceDiffPercent <= maxPriceDiff)
closeKShortCondition = crossUnder and isKCloseCrossUnder and (crossUnderPriceDiffPercent > minPriceDiffShort)
crossUnderBetween50and45 = crossUnder and currentCrossUnderK <= 50 and currentCrossUnderK > 45

// Long to Short if crossunder %K > 80 OR < 60
longToShortCondition = crossUnder and (currentCrossUnderK > 80 or currentCrossUnderK < 60) and strategy.position_size > 0 and is_regular_hours

upperLimit = refD_tf * (1 + tolerance/100)
lowerLimit = refD_tf * (1 - tolerance/100)
withinToleranceLong = primaryK_tf >= lowerLimit and primaryK_tf <= upperLimit
withinToleranceShort = primaryK_tf >= lowerLimit and primaryK_tf <= upperLimit

// Final Entry Conditions with MA filter
longCondition = ((longKCondition and (refD_tf >= 50 or refD_tf < 20)) or kAndRefDDiffClose) and is_regular_hours and not is_exit_time and priceAboveMA
shortCondition = (shortKCondition or (crossUnder and withinToleranceShort and (crossUnderPriceDiffPercent <= maxPriceDiff)) or closeKShortCondition or longToShortCondition or crossUnderBetween50and45) and is_regular_hours and not is_exit_time and priceBelowMA

// Short-to-Long Transition Condition with MA filter
shortToLongCondition = crossOver and currentCrossOverK < 25 and strategy.position_size < 0 and is_regular_hours and not is_exit_time and priceAboveMA

// Tracking for %K crossing under refD_tf
var float lastPrimaryKCrossUnderRefD = na
var float currentPrimaryKCrossUnderRefD = na
var bool isPrimaryKCrossUnderRefD = false

// Check if primary %K crosses under reference %D
isPrimaryKCrossUnderRefD := ta.crossunder(primaryK_tf, refD_tf)

// Update tracking for %K crossing under refD
if isPrimaryKCrossUnderRefD
    lastPrimaryKCrossUnderRefD := currentPrimaryKCrossUnderRefD
    currentPrimaryKCrossUnderRefD := primaryK_tf

// Exit Conditions
if is_exit_time
    strategy.close("Long")
    strategy.close("Short")
else if isPrimaryKCrossUnderRefD and not na(lastPrimaryKCrossUnderRefD) and currentPrimaryKCrossUnderRefD < lastPrimaryKCrossUnderRefD
    strategy.close("Long")
else if (ta.crossunder(primaryK_tf, primaryD_tf) and primaryK_tf < refD_tf and refD_tf < 60)
    strategy.close("Long")

if (ta.crossover(primaryK_tf, primaryD_tf) and primaryK_tf > refD_tf and refD_tf > 20) and not is_exit_time
    strategy.close("Short")

// Track if crossunder happens above 85
var bool crossUnderAbove85 = false

// Detect crossunder above 85
if crossUnder and currentCrossUnderK > 85
    crossUnderAbove85 := true

// Reset condition if %K crosses over %D
if ta.crossover(primaryK_tf, primaryD_tf)
    crossUnderAbove85 := false

// Track previous crossover/crossunder values for Higher Low/Lower High detection
var float prevCrossOverK = na
var float prevCrossUnderK = na

// Update previous values on new crossovers/crossunders
if crossOver
    prevCrossOverK := currentCrossOverK
if crossUnder
    prevCrossUnderK := currentCrossUnderK

// Higher Low and Lower High conditions
higherLowCondition = crossOver and not na(prevCrossOverK) and currentCrossOverK > prevCrossOverK
lowerHighCondition = crossUnder and not na(prevCrossUnderK) and currentCrossUnderK < prevCrossUnderK

// Strategy Entries and Transitions
if longCondition
    strategy.entry("Long", strategy.long)

if shortCondition
    if strategy.position_size > 0  // If in a long position, close it first
        strategy.close("Long")
    strategy.entry("Short", strategy.short)

if shortToLongCondition
    strategy.close("Short")
    if ((longKCondition and (refD_tf >= 50 or refD_tf < 20)) or kAndRefDDiffClose)  // Check full longCondition minus time (already checked)
        strategy.entry("Long", strategy.long)

// Add label for Short to Long Transition
if shortToLongCondition
    label.new(bar_index, na, "T", color=color.green, textcolor=color.white, style=label.style_label_up)

// Add label for Long to Short Transition
if longToShortCondition
    label.new(bar_index, na, "T", color=color.red, textcolor=color.white, style=label.style_label_down)

// Plotting
plot(primaryK_tf, "Primary %K", color=color.white, linewidth=1)
plot(primaryD_tf, "Primary %D", color=color.orange, linewidth=1)
plot(refK_tf, "Reference %K", color=color.navy, linewidth=1)
plot(refD_tf, "Reference %D", color=color.rgb(33, 233, 243), linewidth=2)

// Plot current and last %K only for crossUnder when isKCloseCrossUnder is true and currentCrossUnderK < lastCrossUnderK
plot(crossUnder and isKCloseCrossUnder and currentCrossUnderK < lastCrossUnderK ? currentCrossUnderK : na, "Current CrossUnder %K (Close)", color=color.green, style=plot.style_cross, linewidth=2)
plot(crossUnder and isKCloseCrossUnder and currentCrossUnderK < lastCrossUnderK ? lastCrossUnderK : na, "Last CrossUnder %K (Close)", color=color.red, style=plot.style_cross, linewidth=2)

h0 = hline(85, "Upper Band", color=color.rgb(242, 187, 21))
hline(50, "Middle Band", color=#eaff04)
h1 = hline(20, "Lower Band", color=color.rgb(242, 187, 21))
h2 = hline(40, "Lower Band", color=#787B86)
h3 = hline(60, "Lower Band", color=#787B86)
h = hline(0, "Lower Band", color=#787B86)
h5 = hline(100, "Lower Band", color=#787B86)
fill(h0, h1, color=color.rgb(33, 150, 243, 90), title="Background")
fill(h, h1, color=#1be2781d, title="Background")
fill(h0, h5, color=#e21b742d, title="Background")

// Plot the MA if enabled
plot(useMAFilter ? ma : na, "Moving Average", color=color.yellow, linewidth=2)

// Add plot for visualization (optional)
plot(isPrimaryKCrossUnderRefD ? primaryK_tf : na, "Primary %K CrossUnder RefD", color=color.purple, style=plot.style_cross, linewidth=2)
plot(isPrimaryKCrossUnderRefD and not na(lastPrimaryKCrossUnderRefD) ? lastPrimaryKCrossUnderRefD : na, "Last Primary %K CrossUnder RefD", color=color.fuchsia, style=plot.style_cross, linewidth=2)

// Add new alert conditions
alertcondition(higherLowCondition, title="Stoch Higher Low", message="Stoch Higher Low Pattern Detected")
alertcondition(lowerHighCondition, title="Stoch Lower High", message="Stoch Lower High Pattern Detected")

// Plot markers for Higher Low and Lower High patterns
plot(higherLowCondition ? currentCrossOverK : na, "Higher Low", color=color.green, style=plot.style_cross, linewidth=2)
plot(lowerHighCondition ? currentCrossUnderK : na, "Lower High", color=color.red, style=plot.style_cross, linewidth=2)

// Alert conditions
alertcondition(crossOver, title="Stochastic %K Crossed Over %D", message="Stochastic %K crossed over %D")
alertcondition(crossUnder, title="Stochastic %K Crossed Under %D", message="Stochastic %K crossed under %D")
alertcondition(crossOver and primaryK_tf > 50, title="Stochastic %K Crossed Over %D Above 50", message="Stochastic %K crossed over %D above 50")
alertcondition(crossOver and primaryK_tf > refD_tf, title="Stochastic %K Crossed Over %D Above Reference %D", message="Stochastic %K crossed over %D above Reference %D")
alertcondition(longCondition, title="Long Entry Signal", message="Long entry signal triggered")
alertcondition(shortCondition, title="Short Entry Signal", message="Short entry signal triggered")
alertcondition(shortToLongCondition, title="Short to Long Transition", message="Short to Long transition triggered")
alertcondition(longToShortCondition, title="Long to Short Transition", message="Long to Short transition triggered")
alertcondition(isPrimaryKCrossUnderRefD, title="Primary %K Crossed Under Reference %D", message="Primary %K crossed under Reference %D")
alertcondition(crossOver and primaryK_tf > refD_tf, title="Bullish Crossover Above Ref %D", message="Bull: Dual Stoch")
alertcondition(crossUnder and primaryK_tf < refD_tf, title="Bearish Crossunder Below Ref %D", message="Bear: Dual Stoch")