脱出戦略を追跡する

作者: リン・ハーンチャオチャン,日付: 2023年10月17日 16:36:49
タグ:

img

概要

この戦略は,主に"ドンチアン・チャネル"指標を使用して,トレード・ブレークアウト・トレード戦略を実装する.この戦略は,トレンドを追跡し,ブレークアウト・トレード・アイディアを組み合わせ,主要トレンドの特定に基づいて短周期でブレークアウト・ポイントを探し,トレンドに沿って取引する.また,戦略はストップ・ロストを設定し,各取引のリスク/リターンを制御するために利益レベルを設定する.全体として,戦略はトレンドを追跡し,主要トレンドの方向で取引する利点があります.

戦略の論理

  1. 設定パラメータ ドンチアンチャンネル指標 既定期間は20

  2. EMA移動平均を設定し,デフォルト期間は200です.

  3. リスク/リターン比を設定します デフォルトは1.5です

  4. 長期と短期間のブレイクアウト後に引き戻しパラメータを設定する.

  5. 前回のブレイクが高点か低点か記録する.

  6. ロングシグナル:前回のブレイクが低値だった場合,ドンキアの上部帯とEMA線を上回る価格ブレイク

  7. ショート信号:前回のブレイクが高かった場合,価格はドンチアン下帯とEMA線を下回ります.

  8. ロング エントリー後,ドンキアンの下帯でストップロスを設定し 5ポイントを引いて,リスク/リターン比で利益を取ります.

  9. ストップロスをドンキアンの上部帯プラス5ポイントに設定し リスク/リターン比 ×ストップロスの距離で利益を取ります

この方法では,トレンドフォローとブレークアウトトレードを組み合わせて,主要なトレンドとともに取引します.一方,ストップ・ロストとテイク・プロフィートは,各取引のリスク/リターンを制御します.

利点分析

  1. 主要なトレンドをフォローし,トレンドに反する取引を避ける.

  2. ドンチアン・チャネルは長期指標として EMAフィルターと組み合わせることで,トレンドを効果的に特定することができます.

  3. ストップ・ロスト・アンド・テイク・プロフィート 取引ごとにリスクをコントロールし,潜在的な損失を制限します

  4. リスク/リターン比を最適化することで,利益因子を増加させ,過剰なリターンを追求することができます.

  5. 柔軟なバックテスト パラメータにより 異なる市場での パラメータを最適化できます

リスク分析

  1. ドンチアン・チャネルとEMAは 時々間違った信号を出すことがあります

  2. ブレイクアウト取引は 簡単に罠にはまり 傾向の背景をはっきりと把握する必要があります

  3. 固定ストップ・ロードとテイク・プロフィートは 市場の変動によって調整できない.

  4. パラメータの最適化空間が限られ リアルタイムでのパフォーマンス保証されていません

  5. ブラック・スワン・イベントに脆弱な取引システムは 深刻な損失をもたらす可能性があります

オプティマイゼーションの方向性

  1. シグナル品質を向上させるため 振動器のようなフィルターを追加してみてください

  2. 市場変動とATRに基づいて,適応ストップ損失と利益を取ることを設定します.

  3. マシン学習を使って テストし パラメータを最適化して リアルマーケットに合わせます

  4. エントリーロジックを最適化して 容量や波動性を条件として 罠を避ける.

  5. トレンドフォローするシステムや機械学習を組み合わせて 頑丈性のハイブリッドモデルを作成します

結論

この戦略は,主要なトレンドに沿ってトレードし,トレードごとにリスクを管理するためにストップ・ロスを設定し,利益を上げながらエントリー・シグナルとしてブレイクアウトを取ること.この戦略にはいくつかの利点がありますが,改善の余地もあります.全体として,適切なパラメータチューニング,エントリータイミング,および他の技術との強化により,トレンドフォロー戦略が現実的になることができます.しかし,投資家は常に,いかなる取引システムも市場リスクを完全に排除することができず,リスク管理が不可欠であることを覚えておくべきです.


/*backtest
start: 2023-09-16 00:00:00
end: 2023-10-16 00:00:00
period: 4h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// Welcome to my second script on Tradingview with Pinescript
// First of, I'm sorry for the amount of comments on this script, this script was a challenge for me, fun one for sure, but I wanted to thoroughly go through every step before making the script public
// Glad I did so because I fixed some weird things and I ended up forgetting to add the EMA into the equation so our entry signals were a mess
// This one was a lot tougher to complete compared to my MACD crossover trend strategy but I learned a ton from it, which is always good and fun
// Also I'll explain the strategy and how I got there through some creative coding(I'm saying creative because I had to figure this stuff out by myself as I couldn't find any reference codes)
// First things first. This is a Donchian Channel Breakout strategy which follows the following rules
// If the price hits the upperband of the Donchian Channel + price is above EMA and the price previously hit the lowerband of the Donchian Channel it's a buy signal
// If the price hits the lowerband of the Donchian Channel + price is below EMA and the price prevbiously hit the upper band of the Donchian Channel it's a sell signal
// Stop losses are set at the lower or upper band with a 0.5% deviation because we are acting as if those two bands are the resistance in this case
// Last but not least(yes, this gave BY FAR the most trouble to code), the profit target is set with a 1.5 risk to reward ratio
// If you have any suggestions to make my code more efficient, I'll be happy to hear so from you
// So without further ado, let's walk through the code

// The first line is basically standard because it makes backtesting so much more easy, commission value is based on Binance futures fees when you're using BNB to pay those fees in the futures market
// strategy(title="Donchian Channels", shorttitle="DC", overlay=true, default_qty_type = strategy.cash, default_qty_value = 150, initial_capital = 1000, currency = currency.USD, commission_type = "percent", commission_value = 0.036)
// The built-in Donchian Channels + an added EMA input which I grouped with the historical bars from the Donchian Channels
length          = input(20, minval=1, group = "Indicators")
lower           = lowest(length)
upper           = highest(length)
basis           = avg(upper, lower)
emaInput        = input(title = "EMA Input", type = input.integer, defval = 200, minval = 10, maxval = 400, step = 1, group = "Indicators")
// I've made three new inputs, for risk/reward ratio and for the standard pullback deviation. My advise is to not use the pullback inputs as I'm not 100% sure if they work as intended or not
riskreward      = input(title = "Risk/Reward Ratio", type = input.float, defval = 1.50, minval = 0.01, maxval = 100, step = 0.01, group = "Risk/Reward")
pullbackLong    = input(title = "Distance from Long pullback %", type = input.float, defval = 0.995, minval = 0.001, maxval = 2, step = 0.001, group = "Risk/Reward")
pullbackShort   = input(title = "Distance from Short pullback %", type = input.float, defval = 1.005, minval = 0.001, maxval = 2, step = 0.001, group = "Risk/Reward")

// Input backtest range, you can adjust these in the input options, just standard stuff
fromMonth       = input(defval = 1,    title = "From Month",      type = input.integer, minval = 1, maxval = 12, group = "Backtest Date Range")
fromDay         = input(defval = 1,    title = "From Day",        type = input.integer, minval = 1, maxval = 31, group = "Backtest Date Range")
fromYear        = input(defval = 2000, title = "From Year",       type = input.integer, minval = 1970,           group = "Backtest Date Range")
thruMonth       = input(defval = 1,    title = "Thru Month",      type = input.integer, minval = 1, maxval = 12, group = "Backtest Date Range")
thruDay         = input(defval = 1,    title = "Thru Day",        type = input.integer, minval = 1, maxval = 31, group = "Backtest Date Range")
thruYear        = input(defval = 2099, title = "Thru Year",       type = input.integer, minval = 1970,           group = "Backtest Date Range")
// Date variable also standard stuff
inDataRange     = (time >= timestamp(syminfo.timezone, fromYear, fromMonth, fromDay, 0, 0)) and (time < timestamp(syminfo.timezone, thruYear, thruMonth, thruDay, 0, 0))

// I had to makes these variables because the system has to remember whether the previous 'breakout' was a high or a low
// Also, because I based my stoploss on the upper/lower band of the indicator I had to find a way to change this value just once without losing the value, that was added, on the next bar
var previousishigh = false
var previousislow = false
var longprofit = 0.0
var shortprofit = 0.0
var stoplossLong = 0.0
var stoplossShort = 0.0
// These are used as our entry variables
emaCheck = ema(close, emaInput)
longcond = high >= upper and close > emaCheck
shortcond = low <= lower and close < emaCheck

// With these two if statements I'm changing the boolean variable above to true, we need this to decide out entry position
if high >= upper
    previousishigh := true
if low <= lower
    previousislow := true

// Made a last minute change on this part. To clean up our entry signals we don't want our breakouts, while IN a position, to change. This way we do not instantly open a new position, almost always in the opposite direction, upon exiting one
if strategy.position_size > 0 or strategy.position_size < 0 
    previousishigh := false
    previousislow := false

// Strategy inputs
// Long - previous 'breakout' has to be a low, the current price has to be a new high and above the EMA, we're not allowed to be in a position and ofcourse it has to be within our given data for backtesting purposes
if previousislow == true and longcond and strategy.position_size == 0 and inDataRange
    strategy.entry("Long Entry", strategy.long, comment = "Entry Long")
    stoplossLong := lower * pullbackLong
    longprofit := ((((1 - stoplossLong / close) * riskreward) + 1) * close)
    strategy.exit("Long Exit", "Long Entry", limit = longprofit, stop = stoplossLong, comment = "Long Exit")

// Short - Previous 'breakout' has to be a high, current price has to be a new low and lowe than the 200EMA, we're not allowed to trade when we're in a position and it has to be within our given data for backtesting purposes
if previousishigh == true and shortcond and strategy.position_size == 0 and inDataRange
    strategy.entry("Short Entry", strategy.short, comment = "Entry Short")
    stoplossShort := upper * pullbackShort
    shortprofit := (close - ((((1 - close / stoplossShort) * riskreward) * close)))
    strategy.exit("Short Exit", "Short Entry", limit = shortprofit, stop = stoplossShort, comment = "Short Exit")
    
// This plots the Donchian Channels on the chart which is just using the built-in Donchian Channels
plot(basis, "Basis", color=color.blue)
u = plot(upper, "Upper", color=color.green)
l = plot(lower, "Lower", color=color.red)
fill(u, l, color=#0094FF, transp=95, title="Background")

// These plots are to show if the variables are working as intended, it's a mess I know but I didn't have any better ideas, they work well enough for me
// plot(previousislow ? close * 0.95 : na, color=color.red, linewidth=2, style=plot.style_linebr)
// plot(previousishigh ? close * 1.05 : na, color=color.green, style=plot.style_linebr)
// plot(longprofit, color=color.purple)
// plot(shortprofit, color=color.silver)
// plot(stoplossLong)
// plot(stoplossShort)
// plot(strategy.position_size)

もっと