트레이딩 심리적 통제 균형 전략


생성 날짜: 2024-02-21 14:33:04 마지막으로 수정됨: 2024-02-21 14:33:04
복사: 0 클릭수: 607
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

트레이딩 심리적 통제 균형 전략

개요

이 전략의 목적은 다른 매개 변수를 설정하여 거래자의 심리 및 거래 성능을 균형을 맞추어 더 안정적인 수익을 얻는 것입니다. 그것은 평균선, 브린 벨트, 켈트너 채널과 같은 지표를 사용하여 시장의 추세와 변동률을 판단하고, PSAR 지표와 함께 역전 신호를 판단하고, TTM 엑스트레이션 지표를 사용하여 동력을 판단합니다. 거래 신호는 이러한 지표의 조합으로 생성됩니다. 동시에, 전략은 높은 낮은 중지 및 위험 회수 중지 방식을 사용하여 위험을 관리합니다.

전략 원칙

이 전략의 주요 논리는 다음과 같습니다.

  1. 추세 판단: EMA 평균선을 사용하여 가격 추세 방향을 판단합니다. 가격은 EMA 위쪽은 상승, 아래쪽은 하락입니다.

  2. 판단 역전: 가격 역전점을 판단하기 위해 PSAR을 사용한다. PSAR 포인트는 가격 위쪽에 보이스 신호로 나타나고 가격 아래쪽에 보이스 신호로 나타난다.

  3. 판단량: TTM Squeeze 지표를 사용하여 시장의 변동량과 동력을 판단한다. TTM Squeeze 지표는 부린 밴드와 켈트너 통로의 폭을 비교하여 변동량을 측정한다. 압축은 매우 낮은 변동량을 의미한다. 압축 해제는 변동량이 증가하고 가격이 큰 방향의 움직임을 일으킬 것이라는 신호를 의미합니다.

  4. 거래 신호를 생성: 가격이 EMA 평균선, PSAR 포인트를 통과하고 TTM Squeeze 지표가 압축을 해제 할 때, 볼 수 있는 신호를 생성; 가격이 EMA 평균선, PSAR 포인트를 통과하고 TTM Squeeze 지표가 압축에 들어갈 때, 볼 수 없는 신호를 생성

  5. 중지 방법: 높은 낮은 지점을 중지. 최근 특정 주기의 최고 가격 또는 최저 가격에 따라 세팅 배수를 세우고 중지 지점으로 설정합니다.

  6. 중지 방법: 위험수익비율 자동 중지 사용. 현재 가격으로부터의 위험수익비율의 비율에 따라 설정된 위험수익비율의 변수를 곱하면 중지점을 얻는다.

매개 변수 설정을 통해 거래 주파수, 포지션 관리, 스톱로스 포인트 및 스톱로스 포인트, 균형 거래 심리를 제어할 수 있다.

우위 분석

이 전략은 다음과 같은 장점을 가지고 있습니다.

  1. 다중 지표 판단, 신호 정확도 향상

  2. 역전 주, 역전 보조, 역전 지점을 잡기, 부진을 제거하기 위해 부진을 제거하기 위해 부진을 제거하기 위해 부진을 제거하기 위해

  3. TTMSqueeze 지표는 트렌드에 대한 조정을 효과적으로 판단하여 조정이 유효하지 않은 거래를 피합니다.

  4. 높은 저손실 방식은 간단하고 실용적이며, 시장에 따라 막기 거리를 조정할 수 있습니다.

  5. 리스크 리터드 비 스톱 방식은 수익/손실 비율을 수치화하여 조정할 수 있습니다.

  6. 개인 위험 선호도에 따라 다양한 매개 변수를 조정할 수 있습니다.

위험 분석

이 전략에는 다음과 같은 위험도 있습니다.

  1. 다중 지표 조합 판단은 신호의 정확도를 높여주지만, 엔트리 지점을 뛰어넘는 가능성을 높여줍니다.

  2. 트렌드 상황에서는 역전주 전략이 좋지 않을 수 있습니다.

  3. 높은 낮은 스톱더는 때때로 뚫려서 위험을 완전히 피할 수 없습니다.

  4. 리스크/보너스/스탠드/스탠드/스탠드 (risk/reward/stop) 은 가격의 폭등이나 조정으로 인해 무효화될 수 있습니다.

  5. 잘못된 매개 변수 설정으로 인해 손실 또는 빈번한 중단이 발생할 수 있습니다

최적화 방향

이 전략은 다음과 같은 측면에서 최적화될 수 있습니다.

  1. 더 정확한 신호를 위해 지표 무게를 추가하거나 조정합니다.

  2. 역전 및 트렌드 판단의 지표 파라미터를 최적화하여 수익을 올릴 수 있습니다.

  3. 높은 낮은 스톱 패러미터를 최적화하여 스톱을 합리적으로 만듭니다.

  4. 다양한 리스크/이익 비율을 테스트하여 최적의 결과를 얻습니다.

  5. 단위 손실의 영향을 줄이기 위해 지수 매개 변수를 조정합니다.

요약하다

이 전략은 전체적으로, 지표 집합 판단과 파라미터 조정을 통해 거래 심리를 효과적으로 균형을 잡고 안정적인 긍정적인 수익을 얻을 수 있다. 개선의 여지가 있지만 실제 적용 가치가 있다. 시장 피드백과 파라미터 미세 조정을 통해이 전략은 거래 심리를 제어하고 장기적으로 안정적인 수익을 얻는 효과적인 도구가 될 수 있다.

전략 소스 코드
/*backtest
start: 2024-01-01 00:00:00
end: 2024-01-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/


//@version=5
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © simwai
strategy('Octopus Nest Strategy 🐙', shorttitle='🐙', overlay=true )

// -- Colors --
color maximumYellowRed = color.rgb(255, 203, 98) // yellow
color rajah = color.rgb(242, 166, 84) // orange
color magicMint = color.rgb(171, 237, 198)
color languidLavender = color.rgb(232, 215, 255)
color maximumBluePurple = color.rgb(181, 161, 226)
color skyBlue = color.rgb(144, 226, 244)
color lightGray = color.rgb(214, 214, 214)
color quickSilver = color.rgb(163, 163, 163)
color mediumAquamarine = color.rgb(104, 223, 153)
color carrotOrange = color.rgb(239, 146, 46)

// -- Inputs --
float src = input.source(close, 'Choose Source', group='General', inline='1')
bool isSignalLabelEnabled = input.bool(title='Show Signal Labels?', defval=true, group='General', inline='2')
bool isPsarAdaptive = input.bool(title='Is PSAR Adaptive?', defval=false, group='General', inline='2')

float highLowStopLossMultiplier = input.float(defval=0.98,  step=0.01, minval=0, maxval=1, title='Multiplier', group='High Low Stop Loss', inline='1')
float highLowStopLossBackupMultiplier = input.float(defval=0.98, step=0.01, minval=0, maxval=1, title='Backup Multiplier', group='High Low Stop Loss', inline='1')
int highLowStopLossLookback = input.int(defval=20, step=5, minval=1, title='Lookback', group='High Low Stop Loss', inline='2')
float automaticHighLowTakeProfitRatio = input.float(defval=1.125, step=0.1, minval=0, title='Risk Reward Ratio', group='Automatic High Low Take Profit', inline='2')

int emaLength = input.int(100, minval=2, title='Length', group='EMA', inline='1')
int ttmLength = input.int(title='Length', defval=20, minval=0, group='TTM Squeeze', inline='1')

float psarStart = input.float(0.02, 'Start', step=0.01, minval=0.0, group='PSAR', inline='1')
float psarInc = input.float(0.02, 'Increment', step=0.01, minval=0.01, group='PSAR', inline='1')
float psarMax = input.float(0.2, 'Max', step=0.05, minval=0.0, group='PSAR', inline='2')

startAFactor = input.float(0.02, 'Starting Acceleration Factor', step = 0.001, group='Adaptive PSAR', inline='1')
minStep = input.float(0.0, 'Min Step', step = 0.001, group='Adaptive PSAR', inline='1')
maxStep = input.float(0.02, 'Max Step', step = 0.001, group='Adaptive PSAR', inline='2')
maxAFactor = input.float(0.2, 'Max Acceleration Factor', step = 0.001, group='Adaptive PSAR', inline='2')  

hiloMode = input.string('On', 'HiLo Mode', options = ['Off', 'On'], group='Adaptive PSAR')
adaptMode = input.string('Kaufman', 'Adaptive Mode', options = ['Off', 'Kaufman', 'Ehlers'], group='Adaptive PSAR')
adaptSmth = input.int(5, 'Adaptive Smoothing Period', minval = 1, group='Adaptive PSAR')
filt = input.float(0.0, 'Filter in Pips', group='Adaptive PSAR', minval = 0)
minChng = input.float(0.0, 'Min Change in Pips', group='Adaptive PSAR', minval = 0)
SignalMode = input.string('Only Stops', 'Signal Mode', options = ['Only Stops', 'Signals & Stops'], group='Adaptive PSAR')

// -- Functions --
tr(_high, _low, _close) => math.max(_high - _low, math.abs(_high - _close[1]), math.abs(_low - _close[1]))

// -- Calculation --
var string lastTrade = 'initial'

float _low = low
float _high = high
float _close = close

// -- TTM Squeeze – Credits to @Greeny --
bband(ttmLength, mult) =>
    ta.sma(src, ttmLength) + mult * ta.stdev(src, ttmLength)
keltner(ttmLength, mult) =>
    ta.ema(src, ttmLength) + mult * ta.ema(tr(_high, _low, _close), ttmLength)

e1 = (ta.highest(_high, ttmLength) + ta.lowest(_low, ttmLength)) / 2 + ta.sma(src, ttmLength)
osc = ta.linreg(src - e1 / 2, ttmLength, 0)
diff = bband(ttmLength, 2) - keltner(ttmLength, 1)
osc_color = osc[1] < osc[0] ? osc[0] >= 0 ? #00ffff : #cc00cc : osc[0] >= 0 ? #009b9b : #ff9bff
mid_color = diff >= 0 ? color.green : color.red

// -- PSAR --
// Credits to @Bjorgum
calcBaseUnit() =>
    bool  isForexSymbol = syminfo.type     == 'forex'
    bool  isYenPair     = syminfo.currency == 'JPY'
    float result = isForexSymbol ? isYenPair ? 0.01 : 0.0001 : syminfo.mintick

// Credits to @loxx
_afact(mode,input, per, smooth) =>
    eff = 0., seff = 0.
    len = 0, sum = 0., max = 0., min = 1000000000.
    len := mode == 'Kaufman' ? math.ceil(per) : math.ceil(math.max(20, 5 * per))
    for i = 0 to len 
        if (mode == 'Kaufman') 
            sum += math.abs(input[i] - input[i + 1])
        else
            max := input[i] > max ? input[i] : max
            min := input[i] < min ? input[i] : min
    if (mode == 'Kaufman' and sum != 0) 
        eff := math.abs(input - input[len]) / sum
    else
        if (mode == 'Ehlers' and (max - min) > 0) 
            eff := (input - min) / (max - min)
    seff := ta.ema(eff, smooth)
    seff

hVal2 = nz(high[2]), hVal1 = nz(high[1]), hVal0 = high
lowVal2 = nz(low[2]), lowVal1 = nz(low[1]), lowVal0 = low
hiprice2 = nz(high[2]), hiprice1 = nz(high[1]), hiprice0 = high
loprice2 = nz(low[2]), loprice1 = nz(low[1]), loprice0 = low

upSig = 0., dnSig = 0.
aFactor = 0., step = 0., trend = 0.
upTrndSAR = 0., dnTrndSAR = 0.
length = (2 / maxAFactor - 1)

if (hiloMode == 'On') 
    hiprice0 := high
    loprice0 := low
else
    hiprice0 := src
    loprice0 := hiprice0

if bar_index == 1
    trend := 1
    hVal1 := hiprice1
    hVal0 := math.max(hiprice0, hVal1)
    lowVal1 := loprice1
    lowVal0 := math.min(loprice0, lowVal1)
    aFactor := startAFactor
    upTrndSAR := lowVal0
    dnTrndSAR := 0.
else
    hVal0 := hVal1
    lowVal0 := lowVal1
    trend := nz(trend[1])
    aFactor := nz(aFactor[1])
    inputs = 0.
    inprice = src
    if (adaptMode != 'Off')
        if (hiloMode == 'On') 
            inprice := src
        else 
            inprice := hiprice0
        if (adaptMode == 'Kaufman') 
            inputs := inprice
        else
            if (adaptMode == 'Ehlers') 
                if (nz(upTrndSAR[1]) != 0.)
                    inputs := math.abs(inprice - nz(upTrndSAR[1]))
                else
                    if (nz(dnTrndSAR[1]) != 0.) 
                        inputs := math.abs(inprice - nz(dnTrndSAR[1]))
        step := minStep + _afact(adaptMode, inputs, length, adaptSmth) * (maxStep - minStep)
    else 
        step := maxStep
        
    upTrndSAR := 0., dnTrndSAR := 0., upSig := 0., dnSig := 0.
    
    if (nz(trend[1]) > 0) 
        if (nz(trend[1]) == nz(trend[2]))
            aFactor := hVal1 > hVal2 ? nz(aFactor[1]) + step : aFactor
            aFactor := aFactor > maxAFactor ? maxAFactor : aFactor
            aFactor := hVal1 < hVal2 ? startAFactor : aFactor
        else 
            aFactor := nz(aFactor[1])
            
        upTrndSAR := nz(upTrndSAR[1]) + aFactor * (hVal1 - nz(upTrndSAR[1]))
        upTrndSAR := upTrndSAR > loprice1 ? loprice1 : upTrndSAR
        upTrndSAR := upTrndSAR > loprice2 ? loprice2 : upTrndSAR
    else
        if (nz(trend[1]) == nz(trend[2])) 
            aFactor := lowVal1 < lowVal2 ? nz(aFactor[1]) + step : aFactor
            aFactor := aFactor > maxAFactor ? maxAFactor : aFactor
            aFactor := lowVal1 > lowVal2 ? startAFactor : aFactor
        else
            aFactor := nz(aFactor[1])
            
        dnTrndSAR := nz(dnTrndSAR[1]) + aFactor * (lowVal1 - nz(dnTrndSAR[1]))
        dnTrndSAR := dnTrndSAR < hiprice1 ? hiprice1 : dnTrndSAR
        dnTrndSAR := dnTrndSAR < hiprice2 ? hiprice2 : dnTrndSAR
    
    hVal0 := hiprice0 > hVal0 ? hiprice0 : hVal0
    lowVal0 := loprice0 < lowVal0 ? loprice0 : lowVal0
        
    if (minChng > 0) 
        if (upTrndSAR - nz(upTrndSAR[1]) < minChng * calcBaseUnit() and upTrndSAR != 0. and nz(upTrndSAR[1]) != 0.)
            upTrndSAR := nz(upTrndSAR[1])
        if (nz(dnTrndSAR[1]) - dnTrndSAR < minChng * calcBaseUnit() and dnTrndSAR != 0. and nz(dnTrndSAR[1]) != 0.)
            dnTrndSAR := nz(dnTrndSAR[1])

    dnTrndSAR := trend < 0 and dnTrndSAR > nz(dnTrndSAR[1]) ? nz(dnTrndSAR[1]) : dnTrndSAR
    upTrndSAR := trend > 0 and upTrndSAR < nz(upTrndSAR[1]) ? nz(upTrndSAR[1]) : upTrndSAR
    
    if (trend < 0 and hiprice0 >= dnTrndSAR + filt * calcBaseUnit())
        trend := 1
        upTrndSAR := lowVal0
        upSig := SignalMode == 'Signals & Stops' ? lowVal0 : upSig
        dnTrndSAR := 0.
        aFactor := startAFactor
        lowVal0 := loprice0
        hVal0 := hiprice0
    else if (trend > 0 and loprice0 <= upTrndSAR - filt * calcBaseUnit())
        trend := -1
        dnTrndSAR := hVal0
        dnSig := SignalMode == 'Signals & Stops' ? hVal0 : dnSig
        upTrndSAR := 0.
        aFactor := startAFactor
        lowVal0 := loprice0
        hVal0 := hiprice0
    
psar = upTrndSAR > 0 ? upTrndSAR : dnTrndSAR
psar := isPsarAdaptive ? psar : ta.sar(psarStart, psarInc, psarMax) 
plot(psar, title='PSAR', color=src < psar ? rajah : magicMint, style=plot.style_circles)

// -- EMA --
float ema = ta.ema(src, emaLength)
plot(ema, title='EMA', color=languidLavender)

// -- Signals --
var string isTradeOpen = ''
var string signalCache = ''

bool enterLong = src > ema and ta.crossover(src, psar) and ta.crossover(osc, 0)
bool enterShort = src < ema and ta.crossunder(src, psar) and ta.crossunder(osc, 0)
// bool exitLong = ta.crossunder(src, ema)
// bool exitShort = ta.crossover(src, ema)

if (signalCache == 'long entry')
    signalCache := ''
    enterLong := true
else if (signalCache == 'short entry')
    signalCache := ''
    enterShort := true

if (isTradeOpen == '')
    if (enterLong)
        isTradeOpen := 'long'
    else if (enterShort)
        isTradeOpen := 'short'
else if (isTradeOpen == 'long')
    if (enterLong)
        enterLong := false
else if (isTradeOpen == 'short')
    if (enterShort)
        enterShort := false

plotshape((isSignalLabelEnabled and enterLong and (isTradeOpen == 'long')) ? psar : na, title='LONG', text='L', style=shape.labelup, color=mediumAquamarine, textcolor=color.white, size=size.tiny, location=location.absolute)
plotshape((isSignalLabelEnabled and enterShort and (isTradeOpen == 'short')) ? psar : na, title='SHORT', text='S', style=shape.labeldown, color=carrotOrange, textcolor=color.white, size=size.tiny, location=location.absolute)

// -- High Low Stop Loss and Take Profit --
bool isHighLowStopLossEnabled = true
bool isAutomaticHighLowTakeProfitEnabled = true
bool recalculateStopLossTakeProfit = false
bool isStrategyEntryEnabled = false
bool isLongEnabled = true
bool isShortEnabled = true
bool isStopLossTakeProfitRecalculationEnabled = true

bool longStopLossTakeProfitRecalculation = isStopLossTakeProfitRecalculationEnabled ? true : (lastTrade == 'short' or lastTrade == 'initial')
bool shortStopLossTakeProfitRecalculation = isStopLossTakeProfitRecalculationEnabled ? true : (lastTrade == 'long' or lastTrade == 'initial')

var float longHighLowStopLoss = 0
var float shortHighLowStopLoss = 0

float highLowStopLossLowest = ta.lowest(_low, highLowStopLossLookback)
float highLowStopLossHighest = ta.highest(_high, highLowStopLossLookback)

if (isHighLowStopLossEnabled)
    if (((enterLong and longStopLossTakeProfitRecalculation) or recalculateStopLossTakeProfit) and (isStrategyEntryEnabled ? not(strategy.position_size > 0) : true))
        if (highLowStopLossLowest == _low)
            longHighLowStopLoss := _high * highLowStopLossBackupMultiplier
        else if (highLowStopLossLowest > 0)
            longHighLowStopLoss := highLowStopLossLowest * highLowStopLossMultiplier
            
    if (((enterShort and shortStopLossTakeProfitRecalculation) or recalculateStopLossTakeProfit) and (isStrategyEntryEnabled ? not(strategy.position_size < 0) : true))
        if (highLowStopLossHighest == _high)
            shortHighLowStopLoss := _high * (1 + (1 - highLowStopLossBackupMultiplier))
        else if (highLowStopLossHighest > 0)
            shortHighLowStopLoss := highLowStopLossHighest * (1 + (1 - highLowStopLossMultiplier))
        
plot((isLongEnabled and isHighLowStopLossEnabled and (isTradeOpen == 'long')) ? longHighLowStopLoss : na, 'Long High Low Stop Loss', color=magicMint, style=plot.style_circles, trackprice=false)
plot((isShortEnabled and isHighLowStopLossEnabled and (isTradeOpen == 'short')) ? shortHighLowStopLoss : na, 'Short High Low Stop Loss ', color=rajah, style=plot.style_circles, trackprice=false)

// -- Automatic High Low Take Profit --
var float longAutomaticHighLowTakeProfit = na
var float shortAutomaticHighLowTakeProfit = na

if (isAutomaticHighLowTakeProfitEnabled)
    if (((enterLong and longStopLossTakeProfitRecalculation) or recalculateStopLossTakeProfit) and (isStrategyEntryEnabled ? not(strategy.position_size > 0) : true))
        longHighLowStopLossPercentage = 1 - (longHighLowStopLoss / _close)
        longAutomaticHighLowTakeProfit := _close * (1 + (longHighLowStopLossPercentage  * automaticHighLowTakeProfitRatio))
    if (((enterShort and shortStopLossTakeProfitRecalculation) or recalculateStopLossTakeProfit) and (isStrategyEntryEnabled ? not(strategy.position_size > 0) : true)) 
        shortHighLowStopLossPercentage = 1 - (_close / shortHighLowStopLoss)
        shortAutomaticHighLowTakeProfit := _close * (1 - (shortHighLowStopLossPercentage * automaticHighLowTakeProfitRatio))

plot((isAutomaticHighLowTakeProfitEnabled and isHighLowStopLossEnabled and (isTradeOpen == 'long')) ? longAutomaticHighLowTakeProfit : na, 'Long Automatic High Low Take Profit', color=magicMint, style=plot.style_circles, trackprice=false)
plot((isAutomaticHighLowTakeProfitEnabled and isHighLowStopLossEnabled and (isTradeOpen == 'short')) ? shortAutomaticHighLowTakeProfit : na, 'Short Automatic High Low Take Profit', color=rajah, style=plot.style_circles, trackprice=false)

// log.info('Automatic Long High Low Take Profit: ' + str.tostring(longAutomaticHighLowTakeProfit))
// log.info('Automatic Short High Low Take Profit: ' + str.tostring(shortAutomaticHighLowTakeProfit))

// log.info('Long High Low Stop Loss: ' + str.tostring(longHighLowStopLoss))
// log.info('Short High Low Stop Loss: ' + str.tostring(shortHighLowStopLoss))

bool longHighLowStopLossCondition = ta.crossunder(_close, longHighLowStopLoss)
bool shortHighLowStopLossCondition = ta.crossover(_close, shortHighLowStopLoss)

bool longAutomaticHighLowTakeProfitCondition = ta.crossover(_close, longAutomaticHighLowTakeProfit)
bool shortAutomaticHighLowTakeProfitCondition = ta.crossunder(_close, shortAutomaticHighLowTakeProfit)

bool exitLong = (longHighLowStopLossCondition or longAutomaticHighLowTakeProfitCondition) and strategy.position_size > 0
bool exitShort = (shortHighLowStopLossCondition or shortAutomaticHighLowTakeProfitCondition) and strategy.position_size < 0

plotshape((isSignalLabelEnabled and exitLong and (isTradeOpen == 'long')) ? psar : na, title='LONG EXIT', style=shape.circle, color=magicMint, size=size.tiny, location=location.absolute)
plotshape((isSignalLabelEnabled and exitShort and (isTradeOpen == 'short')) ? psar : na, title='SHORT EXIT', style=shape.circle, color=rajah, size=size.tiny, location=location.absolute)

// Long Exits
if (exitLong)
    strategy.close('long', comment=longAutomaticHighLowTakeProfitCondition ? 'EXIT_LONG_TP' : 'EXIT_LONG_SL')
    isTradeOpen := ''

// Short Exits
if (exitShort)
    strategy.close('short', comment=shortAutomaticHighLowTakeProfitCondition ? 'EXIT_SHORT_TP' : 'EXIT_SHORT_SL')
    isTradeOpen := ''

// Long Entries
if (enterLong and (strategy.position_size == 0))
    strategy.entry('long', strategy.long, comment='ENTER_LONG')

// Short Entries
if (enterShort and (strategy.position_size == 0))
    strategy.entry('short', strategy.short, comment='ENTER_SHORT')

// Save last trade state
if (enterLong or exitLong)
    lastTrade := 'long'
if (enterShort or exitShort)
    lastTrade := 'short'

barcolor(color=isTradeOpen == 'long' ? mediumAquamarine : isTradeOpen == 'short' ? carrotOrange : na)