파동 추세와 다각화된 투자를 기반으로 한 지능형 사이클 트레이딩 전략

WT DCA AO ESA EMA SMA CI VOL
생성 날짜: 2024-12-20 16:42:45 마지막으로 수정됨: 2024-12-20 16:42:45
복사: 0 클릭수: 473
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

파동 추세와 다각화된 투자를 기반으로 한 지능형 사이클 트레이딩 전략

전략 개요

이 전략은 파동 동향 지표 ((Wave Trend) 와 분산 투자 ((Dollar Cost Averaging) 의 개념에 기반한 지능형 거래 시스템이다. 전략은 시장의 변동 동향을 분석하여 시장이 초매 지역에있는 동안 단계적으로 포지션을 구축하고, 시장이 불시장이 확인되는 경우 단계적으로 수익을 얻습니다. 이 전략은 기술 분석과 위험 관리의 장점을 결합하여 시장 주기에 걸쳐 지속적으로 포지션을 축적하고 수익을 얻을 수 있습니다.

전략 원칙

전략의 핵심 논리에는 다음과 같은 핵심 요소가 포함됩니다.

  1. HLC3 가격 평균과 지수 이동 평균 (EMA) 을 사용하여 파동 경향 지표를 계산하여 시장의 과매매 상태를 식별합니다.
  2. 마법의 진동기 (Awesome Oscillator) 를 통해 대주기 트렌드를 판단하고, 황소와 곰 시장의 상태를 결정합니다.
  3. 곰 시장 기간 동안, 가격이 초매 지역에 있을 때, 매장 비율이 초매 정도에 따라 동적으로 조정
  4. 황소 시장이 시작될 때, 시스템은 “황금을 사”라는 신호를 내보냅니다.
  5. 황소 시장 기간 동안, 가격이 과매매 영역에 들어갔을 때, 시스템은 과매매 정도에 따라 점진적으로 지분 수익을 감소시킵니다.
  6. 하파 신호나 상위 시점이 발생하면, 시스템은 모든 포지션을 비워서 수익을 고정합니다.

전략적 이점

  1. 분산 투자로 창고 건설 비용을 절감하고 재고 위험을 효과적으로 회피합니다.
  2. 여러 기술 지표가 교차 검증되어 거래 신호의 신뢰성이 향상됩니다.
  3. 포지션 관리가 유연하며, 시장 상황에 따라 거래량을 조정합니다.
  4. 강인한 방어 성질로, 곰 시장 신호가 발생했을 때 적시에 손실을 막는
  5. 명확한 전략 논리, 다양한 시장 환경에 적응할 수 있는 변수

전략적 위험

  1. 거래가 빈번하게 이루어질 수 있고, 거래비용이 증가할 수 있습니다.
  2. 분산 포지션 전략은 일방적인 급격한 상승 시점에 최적의 매수점을 놓칠 수 있습니다.
  3. 기술적인 지표는 시장의 급격한 변동에 반응하지 않을 수 있습니다.
  4. 잘못된 매개 변수 설정으로 인해 매장 또는 매장 감소 시기가 정확하지 않을 수 있습니다.

전략 최적화 방향

  1. 변동률 지표 도입, 포지션 구축 및 해제 수를 최적화
  2. 트렌드 판단의 정확성을 높이기 위해 더 많은 시장 정서 지표를 추가합니다.
  3. 다양한 시장 주기적 역동성에 따라 변수를 조정하는 적응 변수 시스템을 개발
  4. 재원 관리 모듈을 추가하여 보다 세밀한 포지션 제어

요약하다

이것은 기술 분석과 위험 관리를 유기적으로 결합한 지능형 거래 전략입니다. 파동 추세 지표와 분산 투자 방법을 통해 자금을 안전하게 보호하면서 안정적인 수익 성장을 달성합니다. 전략의 핵심 장점은 다양한 시장 환경에 대한 적응력과 명확한 거래 논리와 위험 제어 장치입니다.

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

//@version=5

// Copyright (c) 2024 Seth Ethington.
// All rights reserved.
//
// If this script provides you Bread then share the Dough!
// BTC (God's Money) Address: bc1qrpxvea8ze4ayj2vtr0slp774rulm898gyhe3ss
//
// Redistribution and use in source and binary forms, 
// whether you tweak it or not, is totally fine, 
// but only if you swear on your life that BTC is God's Money! 
// 
// If you're redistributing the source code, 
// you must keep the above copyright notice and, 
// more importantly, the sacred BTC address!
//


strategy(title="Cipher DCA Strategy", shorttitle="Cipher DCA", overlay=false, initial_capital=100, pyramiding=30, currency=currency.USD,  slippage=1, commission_type=strategy.commission.percent, commission_value=0.1, default_qty_type=strategy.percent_of_equity, process_orders_on_close=true)

// Input parameters for the starting date
startDate = input(timestamp("2019-01-01 00:00:00"), title="Start Date (YYYY-MM-DD HH:MM:SS)")


// Input parameters for the indicator
fastLength = input.int(4, title="Fast Wave Length", group="Wave Calculator")  // Length for EMA smoothing of the price channel
slowLength = input.int(33, title="Slow Wave Length", group="Wave Calculator")  // Length for EMA smoothing of the trend channel
wayOverBoughtLevel = input.float(33, title="Way OverBought Level", group="Wave Calculator")
overBoughtLevel = input.float(25, title="Over Bought Level", group="Wave Calculator")
wayOverSoldLevel = input.float(-33, title="Way Over Sold Level", group="Wave Calculator")
overSoldLevel = input.float(-25, title="Over Sold Level", group="Wave Calculator")
accumulatingLevel = input.float(0, title="Accumulating Level", group="Wave Calculator")


// Calculate the average price (HLC3 = (High + Low + Close) / 3)
averagePrice = hlc3

// Compute the smoothed average price (ESA: Exponential Smoothing Average)
exponentialSmoothingAverage = ta.ema(averagePrice, fastLength)

// Compute the deviation (D) between the price and the smoothed average
priceDeviation = ta.ema(math.abs(averagePrice - exponentialSmoothingAverage), fastLength)

// Compute the commodity index (CI) which is normalized price movement
commodityIndex = (averagePrice - exponentialSmoothingAverage) / (0.015 * priceDeviation)

// Smooth the commodity index to create Wave Trend 1 (WT1)
fastWaveTrend = ta.ema(commodityIndex, slowLength)
// //log.info("fastWaveTrend= " + str.tostring(fastWaveTrend))

// Further smooth WT1 using a simple moving average to create Wave Trend 2 (WT2)
slowWaveTrend = ta.sma(fastWaveTrend, 5)
// //log.info("slowWaveTrend= " + str.tostring(slowWaveTrend))


// Plot the center line (0) for reference
plot(0, color=color.white, title="Center Line")

// Plot overbought and oversold levels
plot(wayOverBoughtLevel, color=color.red, title="Way Overbought")
plot(overBoughtLevel, color=color.red, title="Overbought")
plot(overSoldLevel, color=color.green, title="Oversold")
plot(wayOverSoldLevel, color=color.green, title="Way Oversold")

// Plot WT1 and WT2 as filled areas for better visibility
plot(fastWaveTrend, style=plot.style_area, color=color.new(color.blue, 0), title="Fast Wave")
plot(slowWaveTrend, style=plot.style_area, color=color.new(color.navy, 30), title="Slow Wave")

// Highlight the difference between fastWave vs slowWave
waveTrendDifference = fastWaveTrend - slowWaveTrend

// //log.info("waveTrendDifference=" + str.tostring(waveTrendDifference))
plot(waveTrendDifference, color=color.new(color.yellow, 30),style=plot.style_area, title="WT1 - WT2 Difference") //No transparency

// Plot buy and sell signals at crossovers
isCrossover = ta.cross(fastWaveTrend, slowWaveTrend)
// //log.info("isCrossover=" + str.tostring(isCrossover))
plot(isCrossover ? slowWaveTrend : na, color=(slowWaveTrend - fastWaveTrend > 0 ? color.red : color.green), style=plot.style_circles, linewidth=4, title="Crossover Signals")

float waveTrend = na
if (slowWaveTrend > 0 and fastWaveTrend > 0) 
    waveTrend := math.max(slowWaveTrend, fastWaveTrend)
    // //log.info("Both trends are positive. waveTrend set to max value: " + str.tostring(waveTrend))
else if (slowWaveTrend < 0 and fastWaveTrend < 0)
    waveTrend := math.min(slowWaveTrend, fastWaveTrend)
    // //log.info("Both trends are negative. waveTrend set to min value: " + str.tostring(waveTrend))
else 
    waveTrend := 0
    // //log.info("Trends are mixed. waveTrend set to 0.")

// Time to Sell
isCrossingDown = waveTrendDifference < 0

// Time to Buy
isCrossingUp = waveTrendDifference > 0


//-----------------------------------------------------------


// Detect Bull Market and Bear Market using the Awesome Oscillator
// User input for AO thresholds
ao_threshold = input.float(-10, "AO Bull Market Threshold", minval=-50, maxval=50, step=1, group = "Bear and Bull Thresholds")
ao_cycletop_threshold = input.float(5, "AO Bear Market Threshold", minval=0, maxval=200, step=1, group = "Bear and Bull Thresholds")

// Define the Awesome Oscillator
ao = ta.sma(hl2, fastLength) - ta.sma(hl2, slowLength)

// Convert current bar time to the first day of the month for monthly calculations
currentMonthStart = timestamp(year, month, 1, 0, 0)
prevMonthStart = time - (time - currentMonthStart)

// Calculate AO for the start of the month and previous month
aoCurrentMonth = request.security(syminfo.tickerid, 'M', ao[0])
aoPrevMonth1    = request.security(syminfo.tickerid, 'M', ao[1])
aoPrevMonth2    = request.security(syminfo.tickerid, 'M', ao[2])

// Detect bull market based on monthly AO
isBullMarket = aoCurrentMonth > aoPrevMonth1 and aoPrevMonth1 > aoPrevMonth2 and aoCurrentMonth > ao_threshold

// Detect cycle top based on monthly AO
isBearMarket = aoCurrentMonth > ao_cycletop_threshold and aoPrevMonth1 > aoCurrentMonth

// Detect when a bull market is starting
var bool isBullMarketStarting = na
if (not isBullMarket[1] and isBullMarket)
    isBullMarketStarting := true
else
    isBullMarketStarting := false

// Logging
//log.info("isBullMarket is " + str.tostring(isBullMarket))
//log.info("isCycleTop is " + str.tostring(isBearMarket))

// Plot transparent overlays for Bull Market and Cycle Top
overlayColor = isBullMarket ? color.new(color.green, 80) : isBearMarket ? color.new(color.red, 60) : na
bgcolor(overlayColor, title="Market Condition Overlay")


//----------------------------------------------------------


// Calculate Potential Liquidations and Golden Buy Zones
volLength = input.int(20, "Volume Length", minval=1, group="Golden Buy Indicator")
volStdDevThreshold = input.float(2.0, "Volume Standard Diviation Threshold", step=0.1, group="Golden Buy Indicator")
aoWeeklyThreshold = input.int(0, "Awesome Oscillator Oversold Threshold", step=1, group="Golden Buy Indicator")


// Start Accumulating when the price is oversold or price action is flat
isStartAccumulating = waveTrend <= accumulatingLevel and not isBearMarket

// Start Selling when we are now in a Bull Market
isStartSelling = waveTrend > accumulatingLevel

// Calculate Overbought and Oversold Levels
isOverSold = waveTrend < overSoldLevel
isWayOverSold = waveTrend < wayOverSoldLevel
isOverBought = waveTrend > overBoughtLevel
isWayOverBought = waveTrend > wayOverBoughtLevel
//log.info("isOverSold= " + str.tostring(isOverSold) + " isWayOverSold= " + str.tostring(isWayOverSold) + " isOverBought= " + str.tostring(isOverBought) + " isWayOverBought= " + str.tostring(isWayOverBought))

//Weekly Awesome Oscillator to detect oversold levels
aoWeekly = request.security(syminfo.tickerid, "W", ao)

// Get standard deviation of volume over last 20 bars
volumeStDev = ta.stdev(volume, volLength)

// Detect volume spikes
volumeSpike = volume > (ta.sma(volume, volLength) + volStdDevThreshold * volumeStDev)

isGoldenBuyZone = volumeSpike and aoWeekly < aoWeeklyThreshold and not isBearMarket
plotshape(series=isGoldenBuyZone ? -60 : na, style=shape.triangleup, location=location.absolute, color=color.yellow, size=size.tiny, offset=0, title="Golden Buy Zone")

isMarketTop = volumeSpike and aoWeekly > -aoWeeklyThreshold and isBullMarket
plotshape(series=isMarketTop ? 60 : na, style=shape.triangledown, location=location.absolute, color=color.purple, size=size.tiny, offset=0, title="Market Top")



//---------------------------------------------------------

// Buying and Selling Input parameters for the indicator
isBullMarketStartingPercent = input.float(1.0, title="Starting a Bull Market Percent", step=0.01, group="Buy and Sell")
goldenBuyPercent = input.float(0.00006, title="Golden Buy Percent", step=0.01, group="Buy and Sell")
wayOverSoldPercent = input.float(0.00004, title="Way Over Sold Percent", step=0.01, group="Buy and Sell") 
overSoldPercent = input.float(0.00002, title="Over Sold Percent", step=0.01, group="Buy and Sell")
crossOverPercent = input.float(0.00002, title="Cross Over Percent", step=0.01, group="Buy and Sell")
overBoughtPercent = input.float(0.00005, title="Over Bought Percent", step=0.01, group="Buy and Sell")
wayOverBoughtPercent = input.float(0.00006, title="Way Over Bought Percent", step=0.01, group="Buy and Sell")

//Execute Buy and Sell Strategy
// Execute only if the bar's time is after the start date
if (true)
    if ((isCrossover and isCrossingUp and isStartAccumulating) or isGoldenBuyZone or isBullMarketStarting)
        if (isGoldenBuyZone) 
            strategy.entry("Golden Buy", strategy.long, qty = goldenBuyPercent * strategy.initial_capital)
            //log.info("Golden Buy " + str.tostring(goldenBuyPercent))
        else if (isBullMarketStarting)
            strategy.entry("Bull Buy", strategy.long, qty = isBullMarketStartingPercent * strategy.initial_capital)
            //log.info("Way Over Sold Buy " + str.tostring(wayOverSoldPercent))    
        else if (isWayOverSold) 
            strategy.entry(str.tostring(strategy.opentrades), strategy.long, qty = wayOverSoldPercent * strategy.initial_capital)
            //log.info("Way Over Sold Buy " + str.tostring(wayOverSoldPercent))
        else if (isOverSold)  
            strategy.entry(str.tostring(strategy.opentrades), strategy.long, qty = overSoldPercent * strategy.initial_capital)
            //log.info("Over Sold Buy " + str.tostring(overSoldPercent))
        else if (isCrossover)  
            strategy.entry(str.tostring(strategy.opentrades), strategy.long, qty = crossOverPercent * strategy.initial_capital)
            //log.info("Crossover Buy " + str.tostring(crossOverPercent))
    else if (isCrossover and isCrossingDown and isStartSelling) or isBearMarket or isMarketTop
        if (isBearMarket)
            strategy.close_all("Close all")
            //log.info("Closing All Open Positions")
        else if (isWayOverBought or isMarketTop) 
            int openTrades = strategy.opentrades  // Get the number of open trades
            int tradesToClose = math.floor(openTrades * wayOverBoughtPercent)
            //log.info("# of tradesToClose= " + str.tostring(tradesToClose))
    
            // Loop through and close 100% of the open trades determined
            for i = 0 to tradesToClose
                // Close the trade by referencing the correct index
                strategy.close(str.tostring(openTrades - 1 - i), qty_percent = 100)
                //log.info("Sell 100%: Closed trade # " + str.tostring(openTrades - 1 - i))
        else if (isOverBought) 
            int openTrades = strategy.opentrades  // Get the number of open trades
            int tradesToClose = math.floor(openTrades * overBoughtPercent) 
            //log.info("# of tradesToClose= " + str.tostring(tradesToClose))
    
            // Loop through and close 100% of the open trades determined
            for i = 0 to tradesToClose
                // Close the trade by referencing the correct index
                strategy.close(str.tostring(openTrades - 1 - i), qty_percent = 100)
                //log.info("Sell 100%: Closed trade # " + str.tostring(openTrades - 1 - i))
        else if (isStartSelling)
            strategy.close(str.tostring(strategy.opentrades - 1), qty_percent =50)
            //log.info("Sell 100% of Last Trade: Closed trade # " + str.tostring(strategy.opentrades - 1))