토르트 트레이딩 전략에 기반한 브레이크아웃 역전 모델

저자:차오장, 날짜: 2024-01-29 16:48:00
태그:

img

전반적인 설명

이 전략은 수년 동안 검증 된 유명한 거북 거래 전략에 기반합니다. 최대 5 개의 피라미드 주문으로 길고 짧은 신호를 전송합니다. 이는 전략이 동일한 방향으로 최대 5 개의 주문을 유발할 수 있음을 의미합니다. 좋은 위험과 돈 관리로.

이 전략은 함께 작동하는 2개의 시스템을 결합한다는 점에 유의해야 합니다 (S1과 S2).

전략 논리

포지션 사이징은 거북이 거래자가 위험을 적절히 관리하는 데 매우 중요합니다. 이 포지션 사이징 전략은 시장 변동성과 계정 (이익 및 손실) 에 적응합니다. ATR (평균 진실 범위) 를 기반으로합니다.

구매할 수 있는 유닛은:

unit = (percentage_to_risk/100)*account/atr*syminfo.pointvalue 

당신의 위험 욕구에 따라, 당신은 당신의 계좌의 비율을 증가시킬 수 있습니다. 하지만 거북이 거래자는 1%로 기본입니다. 당신이 계약을 거래하면, 유닛은 기본으로 아래로 둥글게해야합니다.

또한 계정의 가치가 초기 자본보다 낮아지면 위험을 줄이기 위한 추가 규칙이 있습니다. 이 경우, 이 경우에만, 단위 공식은 다음과 같이 대체되어야 합니다.

account := (strategy.equity-strategy.openprofit)*(strategy.equity-strategy.openprofit)/strategy.initial_capital

2개의 시스템이 함께 작동합니다.
브레이크오웃은 새로운 최고 또는 새로운 최저입니다. 새로운 최고가 있다면 우리는 긴 포지션을 열고 반대로 새로운 최저가 있다면 우리는 짧은 포지션을 입력합니다.

우리는 추가 규칙을 추가합니다:
이 추가 규칙은 트레이더가 시스템 1 신호가 건너뛰어 버린 경우 주요 트렌드에있을 수 있습니다. 시스템 1 신호가 건너뛰어 버린 경우 다음 촛불도 새로운 20 일 브레이크 인 경우 S1는 신호를 제공하지 않습니다. 우리는 S2 신호를 기다려야하거나 S1을 다시 활성화하기 위해 새로운 브레이크를하지 않는 촛불을 기다려야합니다.

이점 분석

거북이 전략은 가격이 우리에게 유리하게 움직이면 포지션에 추가 유닛을 추가 할 수 있습니다. 같은 방향으로 최대 5 개의 주문을 추가 할 수 있도록 전략을 구성했습니다. 따라서 가격이 변하면 포지션 크기 공식으로 유닛을 추가합니다.

우리는 첫 번째 주문에 대해 최대 SL를 10%로 설정했습니다. 즉 첫 번째 주문의 가치의 10% 이상을 잃지 않을 것입니다. 그러나 SL가 0.5 * ATR ((20) 로 증가 / 감소하므로 피라미드 주문에서 10% 이상의 손실을 보장하지 않기 때문에 더 많은 손실이 가능합니다.

위험 분석

이 전략의 가장 큰 위험은 너무 큰 포지션입니다. 시장 주문이 주문 배치에 사용되기 때문에, 동시에 여러 개의 거대한 시장 주문을 배치하면 코트에 큰 영향을 미치고 큰 미끄러짐을 일으킬 것입니다. 이것은 엄청난 자본 손실로 이어질 것입니다.

또 다른 위험은 자본 관리 구성이 부적절하다. 예를 들어, 잘못된 스톱 로스 구성 또는 과대 비중은 엄청난 손실로 이어질 수 있다. 이것은 자신의 위험 욕구에 따라 조심스럽게 구성되어야 한다.

최적화

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

  1. ATR 기간, 중지 손실에 대한 ATR 곱셈 등과 같은 다른 매개 변수의 반성과 셔프 비율에 대한 영향을 테스트하십시오. 최적의 매개 변수 조합을 찾으십시오.

  2. 다른 출입 및 출입 규칙을 테스트하십시오. 예를 들어 촛불 패턴을 추가 필터로 사용하십시오.

  3. 다른 종류의 스톱 손실을 시도하십시오. 예를 들어 이동 스톱 손실, 동적 스톱 손실. 이것은 스톱 손실이 발생하는 가능성을 줄일 수 있습니다.

  4. 피라미드 오더의 숫자를 테스트해 보세요. 더 많은 오더를 하면 할수록 레버리지와 위험성이 커집니다. 가장 좋은 균형을 찾으세요.

  5. 주요 사건의 영향을 피하기 위해 특정 기간 동안 거래를 중단하십시오 (예를 들어 미국 비 농부 임금 기록 자료가 공개되기 전에).

요약

전체적으로,이 전략은 중장기 트렌드 거래에 적합한 위험과 보상 사이의 좋은 균형을 이룬다. 거래 체계화, 통제 가능한 위험의 장점이 있다. 전략은 안정성과 수익을 높이기 위해 최적화함으로써 더 향상될 수 있다.


/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gsanson66


//This strategy is based on the famous "Turtle Strategy"
//A well-known strategy which proved its performance during past years 
//@version=5
strategy("TURTLE STRATEGY", overlay=true)


//------------------------------TOOL TIPS--------------------------------//

t1 = "Percentage of the account the trader is willing to lose. This percentage is used to define the position size based on previous gains or losses. Turtle traders default to 1%."
t2 = "ATR Length"
t3 = "ATR Multiplier to fix the Stop Loss"
t4 = "Pyramiding : ATR Multiplier to set a profit target to increase position size"
t5 = "System 1 enter long if there is a new high after this selected period of time"
t6 = "System 2 enter long if there is a new high after this selected period of time"
t7 = "Exit Long from system 1 if there is a new low after this selected period of time"
t8 = "Exit Long from system 2 if there is a new low after this selected period of time"
t9 = "System 1 enter short if there is a new low after this selected period of time"
t10 = "System 2 enter short if there is a new low after this selected period of time"
t11 = "Exit short from system 1 if there is a new high after this selected period of time"
t12 = "Exit short from system 2 if there is a new high after this selected period of time"


//----------------------------------------FUNCTIONS---------------------------------------//

//@function Displays text passed to `txt` when called.
debugLabel(txt, color) =>
    label.new(bar_index, high, text=txt, color=color, style=label.style_label_lower_right, textcolor=color.black, size=size.small)

//@function which looks if the close date of the current bar falls inside the date range
inBacktestPeriod(start, end) => true


//---------------------------------------USER INPUTS--------------------------------------//

//Risk Management and turtle system input
percentage_to_risk = input.float(1, "Risk % of capital", maxval=100, minval=0, group="Turtle Parameters", tooltip=t1) 
atr_period = input.int(20, "ATR period", minval=1, group="Turtle Parameters", tooltip=t2)
stop_N_multiplier = input.float(1.5, "Stop ATR", minval=0.1, group="Turtle Parameters", tooltip=t3)
pyramid_profit = input.float(0.5, "Pyramid Profit", minval=0.01, group="Turtle Parameters", tooltip=t4)
S1_long = input.int(20, "S1 Long", minval=1, group="Turtle Parameters", tooltip=t5)
S2_long = input.int(55, "S2 Long", minval=1, group="Turtle Parameters", tooltip=t6)
S1_long_exit = input.int(10, "S1 Long Exit", minval=1, group="Turtle Parameters", tooltip=t7)
S2_long_exit = input.int(20, "S2 Long Exit", minval=1, group="Turtle Parameters", tooltip=t8)
S1_short = input.int(15, "S1 Short", minval=1, group="Turtle Parameters", tooltip=t9)
S2_short = input.int(55, "S2 Short", minval=1, group="Turtle Parameters", tooltip=t10)
S1_short_exit = input.int(7, "S1 Short Exit", minval=1, group="Turtle Parameters", tooltip=t11)
S2_short_exit = input.int(20, "S2 Short Exit", minval=1, group="Turtle Parameters", tooltip=t12)
//Backtesting period
startDate = input(title="Start Date", defval=timestamp("1 Jan 2020 00:00:00"), group="Backtesting Period")
endDate = input(title="End Date", defval=timestamp("1 July 2034 00:00:00"), group="Backtesting Period")


//----------------------------------VARIABLES INITIALISATION-----------------------------//

//Turtle variables
atr = ta.atr(atr_period)
var float buy_price_long = na
var float buy_price_short = na
var float stop_loss_long = na
var float stop_loss_short = na
float account = na
//Entry variables
day_high_syst1 = ta.highest(high, S1_long)
day_low_syst1 = ta.lowest(low, S1_short)
day_high_syst2 = ta.highest(high, S2_long)
day_low_syst2 = ta.lowest(low, S2_short)
var bool skip = false
var bool unskip_buffer_long = false
var bool unskip_buffer_short = false
//Exit variables
exit_long_syst1 = ta.lowest(low, S1_long_exit)
exit_short_syst1 = ta.highest(high, S1_short_exit)
exit_long_syst2 = ta.lowest(low, S2_long_exit)
exit_short_syst2 = ta.highest(high, S2_short_exit)
float exit_signal = na
//Backtesting period
bool inRange = na


//------------------------------CHECKING SOME CONDITIONS ON EACH SCRIPT EXECUTION-------------------------------//
strategy.initial_capital = 50000
//Checking if the date belong to the range
inRange := inBacktestPeriod(startDate, endDate)

//Checking if the current equity is higher or lower than the initial capital to adjusted position size
if strategy.equity - strategy.openprofit < strategy.initial_capital
    account := (strategy.equity-strategy.openprofit)*(strategy.equity-strategy.openprofit)/strategy.initial_capital
else
    account := strategy.equity - strategy.openprofit

//Checking if we close all trades in case where we exit the backtesting period
if strategy.position_size!=0 and not inRange
    strategy.close_all()
    debugLabel("END OF BACKTESTING PERIOD : we close the trade", color=color.rgb(116, 116, 116))


//--------------------------------------SKIP MANAGEMENT------------------------------------//
    
//Checking if a long signal has been skiped and system2 is not triggered
if skip and high>day_high_syst1[1] and high<day_high_syst2[1]
    unskip_buffer_long := true

//Checking if a short signal has been skiped and system2 is not triggered
if skip and low<day_low_syst1[1] and low>day_low_syst2[1]
    unskip_buffer_short := true

//Checking if current high is lower than previous 20_day_high after a skiped long signal to set skip to false
if unskip_buffer_long
    if high<day_high_syst1[1]
        skip := false
        unskip_buffer_long := false

//Checking if current low is higher than previous 20_day_low after a skiped short signal to set skip to false
if unskip_buffer_short
    if low>day_low_syst1[1]
        skip := false
        unskip_buffer_short := false

//Checking if we have an open position to reset skip and unskip buffers
if strategy.position_size!=0 and skip
    skip := false
    unskip_buffer_long := false
    unskip_buffer_short := false


//--------------------------------------------ENTRY CONDITIONS--------------------------------------------------//

//We calculate the position size based on turtle calculation
unit = (percentage_to_risk/100)*account/atr*syminfo.pointvalue

//Long order for system 1
if not skip and not (strategy.position_size>0) and inRange
    strategy.cancel("Long Syst 2")
    //We check that position size doesn't exceed available equity
    if unit*day_high_syst1>account
        unit := account/day_high_syst1
    stop_loss_long := day_high_syst1 - stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_long < day_high_syst1*0.9
        stop_loss_long := day_high_syst1*0.9
    strategy.order("Long Syst 1", strategy.long, unit, stop=day_high_syst1)
    buy_price_long := day_high_syst1

//Long order for system 2
if skip and not (strategy.position_size>0) and inRange
    //We check that position size doesn't exceed available equity
    if unit*day_high_syst2>account
        unit := account/day_high_syst2
    stop_loss_long := day_high_syst2 - stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_long < day_high_syst2*0.9
        stop_loss_long := day_high_syst2*0.9
    strategy.order("Long Syst 2", strategy.long, unit, stop=day_high_syst2)
    buy_price_long := day_high_syst2

//Short order for system 1
if not skip and not (strategy.position_size<0) and inRange
    strategy.cancel("Short Syst 2")
    //We check that position size doesn't exceed available equity
    if unit*day_low_syst1>account
        unit := account/day_low_syst1
    stop_loss_short := day_low_syst1 + stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_short > day_low_syst1*1.1
        stop_loss_short := day_low_syst1*1.1
    strategy.order("Short Syst 1", strategy.short, unit, stop=day_low_syst1)
    buy_price_short := day_low_syst1

//Short order for system 2
if skip and not (strategy.position_size<0) and inRange
    //We check that position size doesn't exceed available equity
    if unit*day_low_syst2>account
        unit := account/day_low_syst2
    stop_loss_short := day_low_syst2 + stop_N_multiplier*atr
    //We adjust SL if it's greater than 10% of trade value and fix it to 10%
    if stop_loss_short > day_low_syst2*1.1
        stop_loss_short := day_low_syst2*1.1
    strategy.order("Short Syst 2", strategy.short, unit, stop=day_low_syst2)
    buy_price_short := day_low_syst2


//-------------------------------PYRAMIDAL------------------------------------//

//Pyramid for long orders
if close > buy_price_long + (pyramid_profit*atr) and strategy.position_size>0
    //We calculate the remaining capital
    remaining_capital = account - strategy.position_size*strategy.position_avg_price*(1-0.0018)
    //We calculate units to add to the long position
    units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
    if remaining_capital > units_to_add
        //We set the new Stop loss
        stop_loss_long := stop_loss_long + pyramid_profit*atr
        strategy.entry("Pyramid Long", strategy.long, units_to_add)
        buy_price_long := close

//Pyramid for short orders
if close < buy_price_short - (pyramid_profit*atr) and strategy.position_size<0
    //We calculate the remaining capital
    remaining_capital = account + strategy.position_size*strategy.position_avg_price*(1-0.0018)
    //We calculate units to add to the short position
    units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
    if remaining_capital > units_to_add
        //We set the new Stop loss
        stop_loss_short := stop_loss_short - pyramid_profit*atr
        strategy.entry("Pyramid Short", strategy.short, units_to_add)
        buy_price_short := close


//----------------------------EXIT ORDERS-------------------------------//

//Checking if exit_long_syst1 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 1"
    if exit_long_syst1[1] > stop_loss_long
        exit_signal := exit_long_syst1[1]
    else
        exit_signal := stop_loss_long

//Checking if exit_long_syst2 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 2"
    if exit_long_syst2[1] > stop_loss_long
        exit_signal := exit_long_syst2[1]
    else
        exit_signal := stop_loss_long

//Checking if exit_short_syst1 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 1"
    if exit_short_syst1[1] < stop_loss_short
        exit_signal := exit_short_syst1[1]
    else
        exit_signal := stop_loss_short

//Checking if exit_short_syst2 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 2"
    if exit_short_syst2[1] < stop_loss_short
        exit_signal := exit_short_syst2[1]
    else
        exit_signal := stop_loss_short

//If the exit order is configured to close the position at a profit, we set 'skip' to true (we substract commission)
if strategy.position_size*exit_signal>strategy.position_size*strategy.position_avg_price*(1-0.0018)
    strategy.cancel("Long Syst 1")    
    strategy.cancel("Short Syst 1")
    skip := true
if strategy.position_size*exit_signal<=strategy.position_size*strategy.position_avg_price*(1-0.0018)
    skip := false

//We place stop exit orders
if strategy.position_size > 0
    strategy.exit("Exit Long", stop=exit_signal)

if strategy.position_size < 0
    strategy.exit("Exit Short", stop=exit_signal)


//------------------------------PLOTTING ELEMENTS-------------------------------//

plotchar(atr, "ATR", "", location.top, color.rgb(131, 5, 83))
//Plotting enter threshold
plot(day_high_syst1[1], "20 day high", color.rgb(118, 217, 159))
plot(day_high_syst2[1], "55 day high", color.rgb(4, 92, 53))
plot(day_low_syst1[1], "20 day low", color.rgb(234, 108, 108))
plot(day_low_syst2[1], "55 day low", color.rgb(149, 17, 17))
//Plotting Exit Signal
plot(exit_signal, "Exit Signal", color.blue, style=plot.style_circles)
//Plotting our position
exit_long_syst2_plot = plot(exit_long_syst2[1], color=na)
day_high_syst2_plot = plot(day_high_syst2[1], color=na)
exit_short_syst2_plot = plot(exit_short_syst2[1], color=na)
day_low_syst2_plot = plot(day_low_syst2[1], color=na)
fill(exit_long_syst2_plot, day_high_syst2_plot, color=strategy.position_size>0 ? color.new(color.lime, 90) : na)
fill(exit_short_syst2_plot, day_low_syst2_plot, color=strategy.position_size<0 ? color.new(color.red, 90) : na)



더 많은