낮은 피라미드 위험 추적 전략

저자:차오장, 날짜: 2023-12-22 12:56:36
태그:

img

이 전략은 다른 지표의 조합을 통해 가격 움직임의 잠재적 인 낮은 지점을 식별하고 위험을 줄이기 위해 피라미딩을 통해 점진적으로 포지션을 구축합니다. 이 전략은 또한 위험을 효과적으로 제어하기 위해 스톱 로스, 영업 취득 및 트레일 스톱 로스 등의 기능을 통합합니다.

전략 개요

이 전략은 먼저 RSI와 EMA RSI 사이의 차이를 사용하여 잠재적 인 가격 최저치를 식별합니다. 잘못된 신호를 필터링하기 위해 전략은 또한 이동 평균과 멀티 타임프레임 스토카스틱 지표를 결합하여 확인합니다. 낮은 포인트 신호가 확인되면, 긴 포지션은 피라미딩을 통해 그 지점에서 약간 낮은 가격으로 점차적으로 구축됩니다. 전략은 12 개의 추적 오더를 열 수 있으며, 각 오더의 크기가 순차적으로 증가하여 위험을 효과적으로 다양화 할 수 있습니다. 모든 오더는 출출을 위해 전체 스톱 손실을 따르며 각 오더에 대해 별도로 수익을 얻을 수 있습니다. 위험을 더 제어하기 위해 전략은 주식 비율을 기반으로 전체 스톱 손실을 설정합니다.

전략 원칙

이 전략은 세 가지 주요 모듈으로 구성됩니다: 낮은 지점 식별, 피라미드 추적 및 위험 관리.

낮은 지점 식별 모듈RSI와 EMA 사이의 차이를 사용하여 잠재적 인 가격 최저치를 식별합니다. 정확성을 향상시키기 위해 이동 평균 지표와 다중 시간 프레임 스토카스틱 지표가 신호 필터링에 도입됩니다. 가격이 이동 평균 이하이고 스토카스틱 K 라인이 30 이하일 때만 낮은 포인트 신호의 유효성이 확인됩니다.

피라미드 추적 모듈이 전략의 핵심입니다. 낮은 지점 신호가 확인되면 전략은 그 낮은 지점의 0.1% 아래에서 첫 번째 포지션을 열 것입니다. 그 후, 가격이 계속 하락하고 평균 진입 가격의 특정 비율 이하인 한 더 많은 긴 주문이 추가됩니다. 새로운 주문의 크기는 순차적으로 증가합니다. 예를 들어 세 번째 주문은 첫 번째 주문 크기의 3 배입니다. 이 피라미드 추적 접근법은 위험을 평균화하는 데 도움이됩니다. 전략은 최대 12 개의 추적 명령을 허용합니다.

위험 관리 모듈세 가지 측면을 포함합니다. 첫째는 최근 기간의 가장 높은 가격에 기반한 전체 스톱 손실입니다. 모든 주문은이 스톱 손실을 따릅니다. 둘째는 각 주문에 대한 독립적 인 수익 설정으로 입시 가격의 특정 비율에 따라 주문을 닫을 수 있습니다. 셋째는 가장 강력한 위험 제어 방법인 계정 자본의 비율에 기반한 전체 스톱 손실입니다.

전략적 장점

  • 피라미드 추적은 전체 위험을 다양화하면서 개별 주문의 위험을 줄여줍니다.
  • 지표의 조합은 낮은 지점 식별의 정확성을 향상시킵니다.
  • 전체 스톱 로스, 수익 취득 및 후속 스톱 함수
  • 주식 스톱 손실은 상당한 손실으로부터 계정을 보호합니다.
  • 매개 변수들은 위험과 보상을 균형있게 조정할 수 있습니다.

전략 위험

  • 낮은 지점 식별은 여전히 일부 제한이 있습니다, 최고의 입구 지점을 놓칠 수 있습니다 또는 잘못된 신호에 들어갈 수 있습니다
  • 주문을 추가 할 때 불리한 시장에 직면하면 손실이 증가 할 수 있습니다.
  • 이점을 반영하기 위해 상대적으로 긴 기간이 필요합니다.
  • 부적절한 매개 변수 설정은 불충분한 위험 통제로 이어질 수 있습니다.

위의 위험을 줄이기 위해 몇 가지 측면을 최적화 할 수 있습니다.

  1. 낮은 지점 식별 정확도를 향상시키기 위해 표시기를 변경하거나 추가하십시오.
  2. 주문의 수, 간격, 수익률을 차지하는 비율 등을 최적화하여 주문당 위험을 줄이십시오.
  3. 수익을 보호하기 위해 손해를 막는 수준을 적당히 강화합니다.
  4. 유동성이 좋고 큰 변동성을 가진 다른 제품을 테스트합니다.

전략 최적화

이 전략의 더 많은 최적화를 위한 여지가 있습니다.

  1. 낮은 지점 식별을 위해 기계 학습과 같은 더 고급 기술을 도입 시도
  2. 시장 조건에 따라 주문 양, 스톱 로스 레벨 등을 동적으로 조정합니다.
  3. 손실 확장을 피하기 위해 박스 중지 손실 메커니즘을 추가
  4. 재입구 메커니즘 추가
  5. 주식 및 암호화폐에 대한 매개 변수를 최적화합니다.

요약

이 전략은 피라미드 추적 접근을 통해 개별 주문의 위험을 효과적으로 줄이고, 전반적인 스톱 로스, 영리, 트레일링 스톱 기능도 리스크 제어의 매우 좋은 역할을 수행합니다. 그러나 여전히 낮은 포인트 식별 및 기타 측면을 개선 할 여지가 있습니다. 더 발전된 기술을 도입하면 매개 변수 동적 조정, 매개 변수 최적화와 결합하여 추가 할 수 있습니다. 이 전략의 위험 보상 비율은 크게 향상 될 수 있습니다.


/*backtest
start: 2022-12-15 00:00:00
end: 2023-12-21 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © A3Sh
//@version=5

// Strategy that finds potential lows in the price action and spreads the risk by entering multiple positions at these lows.
// The low is detected based on the difference between MTF RSI and EMA based RSI, Moving Average and MTF Stochastic indicators.
// The size of each next position that is entered is multiplied by the sequential number of the position.
// Each separate position can exit when a specified take profit is triggered and re-open when detecting a new potential low.
// All positions are closed when the price action crosses over the dynamic blue stop level line.

// This strategy combines open-source code developed by fellow Tradingview community members: 
// The Lowfinder code is developed by RafaelZioni
// https://www.tradingview.com/script/GzKq2RVl-Low-finder/
// Both the MTF RSI code and the MTF Stochastic code are adapted from the MTFindicators libary written by Peter_O
// https://www.tradingview.com/script/UUVWSpXR-MTFindicators/

// The Stop Level calculation is inspired by the syminfo-mintick tutorial on Kodify.net
// https://kodify.net/tradingview/info/syminfo-mintick/

strategy("LowFinder_PyraMider", 
         overlay=true, pyramiding=99, 
         precision=2,
         initial_capital=10000, 
         default_qty_type=strategy.percent_of_equity, 
         default_qty_value=10,
         commission_type=strategy.commission.percent, 
         commission_value=0.06,
         slippage=1
         )


// Backtest Window
start_time   = input(defval=timestamp("01 April 2021 20:00"), group = "Backtest Window", title="Start Time")
end_time     = input(defval=timestamp("01 Aug 2030 20:00"),   group = "Backtest Window", title="End Time")
window() => true


// Inputs
portfolio_size  = input.float  (100,         group = 'Risk - Portfolio',       title = 'Portfolio %', step=1.0) / 100
leverage        = input.int    (1,           group = 'Risk - Portfolio',       title = 'Leverage', minval = 1)
q_mode          = input.string ('multiply',  group = 'Risk - Order Size',      title = 'Order Size Mode', options = ['base', 'multiply'], tooltip = 'Base mode: the base quantiy for each sequential order. Multiply mode: each quantity is multiplied by order number')
q_mode_m        = input.int    (1,           group = 'Risk - Order Size',      title = 'Order Size Divider (Multiply Mode)',  tooltip = 'Divide Multiply by this number to lower the sequential order sizes')
fixed_q         = input.bool   (false,       group = 'Risk - Order Size',      title = 'Fixed Order Size',     inline = '01', tooltip = 'Use with caution! Overrides all Risk calculations')
amount_q        = input.float  (1,           group = 'Risk - Order Size',      title = '. . Base Currency:',   inline = '01')
sl_on           = input.bool   (false,       group = 'Risk - Stop Loss',       title = 'StopLoss of',          inline = '03')
stopLoss        = input.float  (1.5,         group = 'Risk - Stop Loss',       title = '',   step=0.1,         inline = '03') / 100
sl_mode         = input.string ('equity',    group = 'Risk - Stop Loss',       title = '% of',  options = ['avg_price', 'equity'], inline = '03')
stop_len        = input.int    (100,         group = 'Risk - Stop Level',      title = 'Stop Level Length', tooltip = 'Lookback most recent highest high')
stop_deviation  = input.float  (0.3,         group = 'Risk - Stop Level',      title = 'Deviatation % above Stop Level', step=0.1) / 100
cond2_toggle    = input.bool   (true ,       group = 'Risk - Take Profit',     title = 'Take Profit/Trailing Stop', inline = '04')
tp_all          = input.float  (1.0,         group = 'Risk - Take Profit',     title = '..........%', step=0.1,     inline = '04') / 100
tp_on           = input.bool   (true,        group = 'Risk - Take Profit',     title = 'Exit Crossover Take Profit and .....', inline = '02')
exit_mode       = input.string ('stoplevel', group = 'Risk - Take Profit',     title = '',   options = ['close', 'stoplevel'], inline = '02')
takeProfit      = input.float  (10.0,        group = 'Risk - Take Profit',     title = 'Take Profit % per Order', tooltip = 'Each separate order exits when hit', step=0.1)
posCount        = input.int    (12,          group = 'Pyramiding Settings',    title = 'Max Number of Orders')
next_entry      = input.float  (0.2,         group = 'Pyramiding Settings',    title = 'Next Order % below Avg. Price', step=0.1)
oa_lookback     = input.int    (0,           group = 'Pyramiding Settings',    title = 'Next Order after X candles', tooltip = 'Prevents opening too much orders in a Row')
len_rsi         = input.int    (5,           group = 'MTF LowFinder Settings', title = 'Lookback of RSI')
mtf_rsi         = input.int    (1,           group = 'MTF LowFinder Settings', title = 'Higher TimeFrame Multiplier RSI',  tooltip='Multiplies the current timeframe by specified value')
ma_length       = input.int    (26,          group = 'MTF LowFinder Settings', title = 'MA Length / Sensitivity')
new_entry       = input.float  (0.1,         group = 'MTF LowFinder Settings', title = 'First Order % below Low',step=0.1, tooltip = 'Open % lower then the found low')/100
ma_signal       = input.int    (100,         group = 'Moving Average Filter',  title = 'Moving Average Length')
periodK         = input.int    (14,          group = 'MTF Stochastic Filter',  title = 'K',      minval=1)
periodD         = input.int    (3,           group = 'MTF Stochastic Filter',  title = 'D',      minval=1)
smoothK         = input.int    (3,           group = 'MTF Stochastic Filter',  title = 'Smooth', minval=1)
lower           = input.int    (30,          group = 'MTF Stochastic Filter',  title = 'MTF Stoch Filter (above gets filtered)')
mtf_stoch       = input.int    (10,          group = 'MTF Stochastic Filter',  title = 'Higher TimeFrame Multiplier', tooltip='Multiplies the current timeframe by specified value')
avg_on          = input.bool   (true,        group = 'Plots',                  title = 'Plot Average Price')
plot_ma         = input.bool   (false,       group = 'Plots',                  title = 'Plot Moving Average')
plot_ts         = input.bool   (false,       group = 'Plots',                  title = 'Plot Trailing Stop Level')


// variables //
var entry_price     = 0.0    // The entry price of the first entry
var previous_entry  = 0.0    // Stores the price of the previous entry
var iq              = 0.0    // Inititial order quantity before risk calculation
var nq              = 0.0    // Updated new quantity after the loop
var oq              = 0.0    // Old quantity at the beginning or the loop
var q               = 0.0    // Final calculated quantity used as base order size
var int order_after = 0



// Order size calaculations // 

// Order size based on max amount of pyramiding orders or fixed by user input ///
// Order size calculation based on 'base' mode or ' multiply' mode //
if fixed_q
    q := amount_q
else if q_mode == 'multiply'
    iq := (math.abs(strategy.equity * portfolio_size  / posCount) / open) * leverage
    oq := iq
    for i = 0 to posCount
        nq := oq + (iq * ( i/ q_mode_m + 1))
        oq := nq 
    q := (iq  * posCount /  oq) * iq

else
    q := (math.abs(strategy.equity * portfolio_size  / posCount) / open) * leverage

// Function to calcaulate final order size based on order size modes and round the result with 1 decimal //
quantity_mode(index,string q_mode) =>
    q_mode == 'base' ? math.round(q,1) : q_mode == 'multiply' ? math.round(q * (index/q_mode_m  + 1),1) : na



// LowFinder Calculations //
// MTF RSI by Peter_O //
rsi_mtf(float source, simple int mtf,simple int len) =>
    change_mtf=source-source[mtf]
    up_mtf = ta.rma(math.max(change_mtf, 0), len*mtf)
    down_mtf = ta.rma(-math.min(change_mtf, 0), len*mtf)
    rsi_mtf = down_mtf == 0 ? 100 : up_mtf == 0 ? 0 : 100 - (100 / (1 + up_mtf / down_mtf))

// Lowfinder by RafaelZioni //
vrsi = rsi_mtf(close,mtf_rsi,len_rsi)

pp=ta.ema(vrsi,ma_length)
dd=(vrsi-pp)*5
cc=(vrsi+dd+pp)/2

lows=ta.crossover(cc,0) 



// MTF Stoch Calcualation // MTF Stoch adapted from  Peter_O //
stoch_mtfK(source, mtf, len) =>

    k = ta.sma(ta.stoch(source, high, low, periodK * mtf), smoothK * mtf)
    
stoch_mtfD(source, mtf, len) =>

    k = ta.sma(ta.stoch(source, high, low, periodK * mtf), smoothK * mtf)
    d = ta.sma(k, periodD * mtf)
    
mtfK = stoch_mtfK(close, mtf_stoch, periodK)
mtfD = stoch_mtfD(close, mtf_stoch, periodK)



// Open next position % below average position price //
below_avg = close < (strategy.position_avg_price * (1 - (next_entry / 100)))



// Moving Average Filter //
moving_average_signal = ta.sma(close, ma_signal)
plot (plot_ma ? moving_average_signal : na, title = 'Moving Average', color = color.rgb(154, 255, 72))



// Buy Signal //
buy_signal = lows and close < moving_average_signal and mtfK < lower
// First Entry % Below lows //
if buy_signal
    entry_price := close * (1 - new_entry)



// Plot Average Price of Position//
plot (avg_on  ? strategy.position_avg_price : na, title = 'Average Price', style = plot.style_linebr, color = color.new(color.white,0), linewidth = 1)



// Take profit per Open Order //
take_profit_price = close * takeProfit / 100 / syminfo.mintick



// Calculate different Stop Level conditions to exit All //

// Stop Level Caculation //
stop_long1_level = ta.highest (high, stop_len)[1]  * (1 + stop_deviation)
stop_long2_level = ta.highest (high, stop_len)[2]  * (1 + stop_deviation)
stop_long3_level = ta.highest (high, stop_len)[3]  * (1 + stop_deviation)
stop_long4_level = ta.highest (high, stop_len)[1]  * (1 - 0.008) 
// Stop triggers //
stop_long1 = ta.crossover(close,stop_long1_level)
stop_long2 = ta.crossover(close,stop_long2_level)
stop_long4 = ta.crossunder(close,stop_long4_level)
// Exit Conditions, cond 1 only Stop Level, cond2 Trailing Stop option //
exit_condition_1 = close < strategy.position_avg_price ? stop_long1 : close > strategy.position_avg_price ? stop_long2 : na
exit_condition_2 = close < strategy.position_avg_price * (1 + tp_all) ? stop_long2 : 
                   close > strategy.position_avg_price * (1 + tp_all) ? stop_long4 :
                   close < strategy.position_avg_price ? stop_long1 : na
// Switch between conditions //
exit_conditions = cond2_toggle ? exit_condition_2 : exit_condition_1

// Exit when take profit //
ex_m = exit_mode == 'close' ? close : stop_long2_level
tp_exit = ta.crossover(ex_m, strategy.position_avg_price * (1 + tp_all)) and close > strategy.position_avg_price * 1.002

// Plot stoplevel, take profit level //
plot_stop_level    = strategy.position_size > 0 ? stop_long2_level : na
plot_trailing_stop = cond2_toggle and plot_ts and strategy.position_size > 0 and close > strategy.position_avg_price * (1 + tp_all) ? stop_long4_level : na

plot(plot_stop_level,    title = 'Stop Level',    style=plot.style_linebr, color = color.new(#41e3ff, 0), linewidth = 1)
plot(plot_trailing_stop, title = 'Trailing Stop', style=plot.style_linebr, color = color.new(#4cfca4, 0), linewidth = 1)

plot_tp_level = cond2_toggle and strategy.position_size > 0 ? strategy.position_avg_price * (1 + tp_all) : na
plot(plot_tp_level, title = 'Take Profit Level', style=plot.style_linebr, color = color.new(#ff41df, 0), linewidth = 1)



// Calculate Stop Loss based on equity and average price //
loss_equity = ((strategy.position_size * strategy.position_avg_price) - (strategy.equity * stopLoss)) / strategy.position_size
loss_avg_price = strategy.position_avg_price * (1 - stopLoss)
stop_loss = sl_mode == 'avg_price' ? loss_avg_price : loss_equity
plot(strategy.position_size > 0  and sl_on ? stop_loss : na, title = 'Stop Loss', color=color.new(color.red,0),style=plot.style_linebr, linewidth = 1)



// Enter first position //
if ta.crossunder(close,entry_price) and window() and strategy.position_size == 0
    strategy.entry('L_1', strategy.long, qty = math.round(q,1), comment = '+' + str.tostring(math.round(q,1)))
    previous_entry := close


// Enter next pyramiding positions //
if buy_signal and window() and strategy.position_size > 0 and below_avg
    order_after := order_after + 1
    for i = 1 to strategy.opentrades
        entry_comment = '+' + str.tostring((quantity_mode(i,q_mode))) // Comment with variable //
        if strategy.opentrades == i and i < posCount and order_after > oa_lookback
            entry_price := close
            entry_id = 'L_' + str.tostring(i + 1) 
            strategy.entry(id = entry_id, direction=strategy.long, limit=entry_price, qty= quantity_mode(i,q_mode), comment = entry_comment)
            previous_entry := entry_price
            order_after := 0


// Exit per Position //
if strategy.opentrades > 0 and window() 
    for i = 0 to strategy.opentrades 
        exit_comment = '-' + str.tostring(strategy.opentrades.size(i))
        exit_from = 'L_' + str.tostring(i + 1)
        exit_id = 'Exit_' + str.tostring(i + 1)
        strategy.exit(id= exit_id, from_entry= exit_from, profit = take_profit_price, comment = exit_comment)
            

// Exit All //
if exit_conditions or (tp_exit and tp_on and cond2_toggle) and window()
    strategy.close_all('Exti All')
    entry_price := 0

if ta.crossunder(close,stop_loss)  and sl_on and window()
    strategy.close_all('StopLoss')
    entry_price := 0
    





더 많은