低ピラミッドリスク追跡戦略

作者: リン・ハーンチャオチャン, 日付: 2023-12-22 12:56:36
タグ:

img

この戦略は,異なる指標の組み合わせを通じて価格動きの潜在的な低点を特定し,リスクを減らすためにピラミディングを通じて徐々にポジションを構築する.戦略には,リスクを効果的に制御するためにストップ・ロスト,テイク・プロフィート,トライリング・ストップ・ロストなどの機能も含まれます.

戦略の概要

この戦略は,まずRSIとEMA RSIの違いを使用して,潜在的な値下げを特定する.偽信号をフィルタリングするために,戦略は確認のために移動平均値とマルチタイムフレームストキャスティックインジケーターも組み合わせます.低点信号が確認されると,ロングポジションはピラミディングを通じて,その時点から少し低い価格で徐々に構築されます. 戦略は,順番に 12 トラッキングオーダーを開くことができます.各オーダーのサイズが増加することで,リスクを効果的に多様化することができます. すべてのオーダーは,各オーダーで個別に利益を得ることができる一方で,退出するために全体的なストップ損失をフォローします. さらにリスクを管理するために,戦略は,株式パーセントに基づいて全体的なストップ損失を設定します.

戦略原則

戦略は3つの主要モジュールから構成されています.低点の特定,ピラミッド追跡,リスク管理です.

について低点識別モジュールRSIとEMAの違いを使用して,潜在的な価格低位を特定する.正確性を向上させるために,シグナルフィルタリングのために移動平均指標とマルチタイムフレームストーカスティック指標が導入される.価格が移動平均値を下回り,ストーカスティックK線が30を下回る場合にのみ,低点信号の有効性が確認される.

についてピラミッド追跡モジュールこの戦略の核心である.低点信号が確認されると,戦略はその低点より0.1%低い位置で最初のポジションを開く.その後,価格が低下し続け,平均入場価格の一定のパーセントを下回る限り,より多くのロングオーダーは追加されます.新しいオーダーのサイズは順番に増加します.例えば,第3オーダーは最初のオーダーのサイズの3倍です.このピラミッド追跡アプローチはリスクを平均するのに役立ちます.戦略は最大12のトラッキングオーダーを可能にします.

についてリスク管理モジュール3つの側面を含みます.第一は最近の最高価格に基づく全体的なストップ損失です.すべてのオーダーはこのストップ損失をフォローします.第二は,エントリー価格の特定のパーセントに基づいてオーダーを閉鎖することを可能にする各オーダーの独立した取利益設定です.第三は,最も強力なリスク制御方法であるアカウントの資本のパーセントに基づいて全体的なストップ損失です.

戦略 の 利点

  • ピラミッドトラッキングは,個々の注文のリスクを軽減し,全体的なリスクを多様化させる
  • 指標の組み合わせにより,低点識別の精度は向上します
  • 総ストップ・ロスト,収益の引き上げ,ストップ・フォロー機能は,リスクを効果的に制御する
  • 株式ストップ損失は,重要な損失からアカウントを保護します.
  • パラメータはリスクと報酬をバランスするように調整できます

戦略リスク

  • 低点識別はまだいくつかの制限があります 最良のエントリーポイントを見逃すか,誤った信号に入る可能性があります
  • オーダーを追加するときに不利な市場に直面すると損失を増やす可能性があります
  • 利点を反映するために比較的長い期間が必要である
  • 適切なパラメータ設定が不十分なリスク管理につながる可能性があります.

上記のリスクを減らすために,いくつかの側面を最適化することができます:

  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
    





もっと