ブレイクバンド 固定ストップ損失戦略

作者: リン・ハーンチャオチャン開催日:2023年11月3日 (月) 14:31:21
タグ:

img

概要

この戦略の主なアイデアは,トレンド方向を特定し,リスク管理のために固定ストップ損失を組み合わせるためのブレイクアウトバンドを使用することです.この戦略は,最初にブレイクアウトバンドを形成するために一定の期間中の最高値と最低値を計算します.価格がブレイクアウトバンドを突破すると,取引信号が生成されます.また,この戦略は,トレーダーに固定ストップ損失額を設定することを可能にします.取引が行われるたびに,システムは固定ストップ損失額に基づいてポジションサイズを計算し,各損失が固定されます.

戦略原則

戦略は4つの主要部分からなる. ポジション管理,ブレイクバンドの特定,ストップ損失設定,ポジションサイズ.

まず,戦略は,開いたポジションがあるかどうかをチェックします.開いている場合は,新しい信号が生成されません.

2つ目は,ストラテジーはブレイクバンドを形成するために,一期間の最高値と最低値を計算する.価格がバンドを突破すると,取引信号が生成される.特に,価格が上部バンドを突破すると,ロング信号が生成される.価格が下部バンドを下回ると,ショート信号が生成される.

さらに,ロング信号が生成されたとき,ストップ・ロスはストップ・ロストとしてブレイクアウト帯の真ん中点を設定する.ストップ・ロスはストップ・ロストとして設定する.ストップ・ロスはストップ・ロストとして設定する.ストップ・ロスはストップ・ロストとして設定する.ストップ・ロスはストップ・ロストとして設定する.ストップ・ロスはストップ・ロストとして設定する.ストップ・ロスはストップ・ロストとして設定する.ストップ・ロスはストップ・ロストとして設定する.ストップ・ロスはストップ・ロストとして設定する.

最後に,ストップロスの固定額を設定することが可能である.シグナルが生成されたとき,ストップロスの現在の価格へのピップ数を計算し,ティックサイズや為替レートなどの要因を組み合わせ,ストップロスの現在の価格との間の価格変化を貨幣的な観点から決定する.ポジションサイズは,固定ストップロスの金額に基づいて計算される.

上記は戦略の主な原則である.ブレークアウト帯でトレンド方向を特定し,固定ストップ損失でリスクを制御することは,基本的な概念である.

利点

このブレイクバンド固定ストップ損失戦略には以下の利点があります.

  1. 先進的なストップ損失概念.この戦略は,固定ストップ損失距離の代わりに固定ストップ損失金額を使用する.これは異なるティック値を持つ製品間でリスクを固定できない問題を回避する.リスク管理の観点から,固定貨幣ストップ損失はより高度である.

  2. 合理的なポジションサイズ: 戦略は,固定ストップ損失額に基づいてポジションサイズを賢く計算し,取引毎の損失を制御し,それによってリスクを合理的に管理することができます.

  3. シンプルで効果的なブレイクアウト識別.バンドでブレイクアウトを識別することはシンプルで直接的で,トレンド方向を効果的に特定することができます.単一の価格レベルのブレイクアウトと比較して,このブレイクアウトバンド識別はトレンドからより多くの誤った信号を避けることができます.

  4. ストップ損失を遅らせることで利益が増加します.ストップ損失を遅らせるためにリアルタイムでストップ損失を調整する戦略の能力は,より多くの利益をロックするのに役立ちます.

  5. 広範囲に適用可能.この戦略はあらゆる製品に適用可能である.パラメータが適切に設定されている限り,固定金額のストップ損失リスク制御が達成され,この戦略は非常に汎用的である.

  6. クリーンなコード構造 コード構造は明確でモジュール化されており,理解し最適化するのが簡単です

リスク

この戦略には,利点にもかかわらず,いくつかのリスクがあります.

  1. ブレイクパターンの品質はテストされていない.この戦略はブレイクパターンの品質を判断せず,いくつかの低品質の信号を生成することがあります.信号をフィルターするために他の指標が必要です.

  2. 固定ストップ損失は機械的すぎることもある.市場価格はしばしばギャップである.固定ストップ損失は規則にあまりにも依存し,調整に柔軟性がない可能性があります.

  3. 取引頻度に制限はない.戦略は取引頻度を制限していないし,取引頻度があまりにも頻繁に取引される可能性がある.頻度を制限するために他の規則が必要である.

  4. 固定ストップ損失はパラメータ設定に依存する. 固定ストップ損失額を設定することは,全体的なリスク管理にとって極めて重要であり,資本規模,リスク意欲なども考慮する必要がある.

  5. ブレイクアウト方向は間違った信号を与える可能性があります.価格の振動や引き下げ中に間違ったブレイクアウト信号が発生することがあります.戦略を最適化するためにより多くの条件が必要です.

  6. 利益の取り込みメカニズムがない.戦略は現在,利益を積極的にロックする利益の取り込み能力がない.これは満足のいく利益につながる可能性があります.

これらのリスクに対処するために,戦略を最適化するいくつかの方法は以下の通りです.

  1. 信号の質をフィルターする指標を追加する,例えばMACD,KDなど.

  2. 質を評価するための突破強度指標を組み込む.例えば,容量の変化によって強度を判断する.

  3. オープン取引の頻度制限を追加する,例えば1日1回の取引.

  4. 固定ストップロスのロジックを最適化する.例えば,一定値を超える割合に基づくストップロスのことです.

  5. 他のフィルターを追加する.例えば,変動,ストップロスの強化など.

  6. 利益を得る戦略を組み込む,例えば抵抗に近い利益を得る.

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

分析に基づいて,戦略は以下の側面で最適化することができます:

  1. 複数の技術指標を用いて信号の質を向上させるフィルターを追加し 傾向の質を評価し 突破強度を判断します

  2. 柔軟性のためにストップロスを最適化する. 特定のリトラセーション後にパーセントベースのトラリングストップに切り替えることができる. 変動に基づいて動的に最適化することもできる.

  3. 取引頻度を制御し,時間帯や頻度にフィルターを追加することで過剰な取引を避ける.

  4. タイミングを良くするために傾向指標を組み込む,例えば傾向の確認を待つ.

  5. 利潤目標,利潤停止,不安定停止などを通じて収益性を向上させる利潤戦略を最適化する

  6. バックテストに基づくリスクパラメータの最適化 例えば固定ストップ金額,ブレイクアウト期間など

  7. 信号,フィルター,リスク,利益のモジュールをさらに切り離すことで より拡張性の良いコードをリファクタリングします

  8. 複数の製品をテストし,異なる製品組み合わせの優位性を評価する.

これらの最適化次元を通じて,ブレイクアウトストップ損失戦略はより堅牢で収益性が高くなり,より多くの戦略組み合わせに拡大するための基盤を築くことができます.

結論

戦略は,トレンドと固定金額のストップをリスク制御のために識別するためにブレークアウトバンドを使用することが合理的です. リスク管理のためのコンセプトは進歩的です. ポジションサイジング論理は,取引ごとに損失を制御するためにも健全です. しかし,戦略は,信号品質,ストップ損失の柔軟性,収益性,などを改善するためのさまざまな最適化によって強化することができます. 傾向フィルターを組み込むこと,利益を取ることを改善し,取引頻度を厳格に制御することで,重要な改善を達成することができます. 結論として,戦略はリスク管理とポジションサイジング技術を学ぶための枠組みを提供し,より複雑な仲介およびマルチ戦略システムへのさらなる研究のための基礎を築きます.


/*backtest
start: 2023-10-26 00:00:00
end: 2023-10-28 03:00:00
period: 10m
basePeriod: 1m
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/
//@version=4
//@author=Takazudo

strategy("Fixed price SL",
  overlay=true,
  default_qty_type=strategy.fixed,
  initial_capital=0,
  currency=currency.USD)

var COLOR_TRANSPARENT = color.new(#000000, 100)
var COLOR_ENTRY_BAND = color.new(#43A6F5, 30)

//============================================================================
// config
//============================================================================

// Money management
_g1 = 'Money management'
var config_riskPrice = input(100, minval=1, title="Risk price for each entry", group=_g1)
var config_depositCurrency = input(title="Deposit currency", type=input.string, defval="USD", options=["USD"], group=_g1)

// Entry strategy
_g2 = 'Entry strategy'
var config_entryBandBars = input(defval = 100, title = "Entry band bar count",  minval=1, group=_g2)

// Backtesting range
_g3 = 'Backtesting range'
fromYear  = input(defval = 2018, title = "From Year",  minval = 1970, group=_g3)
fromMonth = input(defval = 1,    title = "From Month", minval = 1, maxval = 12, group=_g3)
fromDay   = input(defval = 1,    title = "From Day",   minval = 1, maxval = 31, group=_g3)
toYear  = input(defval = 2020, title = "To Year",  minval = 1970, group=_g3)
toMonth = input(defval = 12,    title = "To Month", minval = 1, maxval = 12, group=_g3)
toDay   = input(defval = 31,    title = "To Day",   minval = 1, maxval = 31, group=_g3)

//============================================================================
// exchange caliculations
//============================================================================

// mico pip size caliculation
// ex1: AUDCAD -> 0.0001
// ex2: USDJPY -> 0.01
f_calcMicroPipSize() =>
    _base = syminfo.basecurrency
    _quote = syminfo.currency
    _result = 0.0001
    if _quote == 'JPY'
        _result := _result * 100
    if _base == 'BTC'
        _result := _result * 100
    _result

// convert price to pips
f_convertPriceToPips(_price) =>
    _microPipSize = f_calcMicroPipSize()
    _price / _microPipSize

// caliculate exchange rate between deposit and quote currency
f_calcDepositExchangeSymbolId() =>
    _result = ''
    _deposit = config_depositCurrency
    _quote = syminfo.currency
    if (_deposit == 'USD') and (_quote == 'USD')
        _result := na
    if (_deposit == 'USD') and (_quote == 'AUD')
        _result := 'OANDA:AUDUSD'
    if (_deposit == 'EUR') and (_quote == 'USD')
        _result := 'OANDA:EURUSD'
    if (_deposit == 'USD') and (_quote == 'GBP')
        _result := 'OANDA:GBPUSD'
    if (_deposit == 'USD') and (_quote == 'NZD')
        _result := 'OANDA:NZDUSD'
    if (_deposit == 'USD') and (_quote == 'CAD')
        _result := 'OANDA:USDCAD'
    if (_deposit == 'USD') and (_quote == 'CHF')
        _result := 'OANDA:USDCHF'
    if (_deposit == 'USD') and (_quote == 'JPY')
        _result := 'OANDA:USDJPY'
    _result

// Let's say we need CAD to USD exchange
// However there's only "OANDA:USDCAD" symbol.
// Then we need to invert the exhchange rate.
// this function tells us whether we should invert the rate or not
f_calcShouldInvert() =>
    _result = false
    _deposit = config_depositCurrency
    _quote = syminfo.currency
    if (_deposit == 'USD') and (_quote == 'CAD')
        _result := true
    if (_deposit == 'USD') and (_quote == 'CHF')
        _result := true
    if (_deposit == 'USD') and (_quote == 'JPY')
        _result := true
    _result

// caliculate how much quantity should I buy or sell
f_calcQuantitiesForEntry(_depositExchangeRate, _slPips) =>
    _microPipSize = f_calcMicroPipSize()
    _priceForEachPipAsDeposit = _microPipSize * _depositExchangeRate
    _losePriceOnSl = _priceForEachPipAsDeposit * _slPips
    floor(config_riskPrice / _losePriceOnSl)

//============================================================================
// Quantity caliculation
//============================================================================

depositExchangeSymbolId = f_calcDepositExchangeSymbolId()

// caliculate deposit exchange rate
rate = security(depositExchangeSymbolId, timeframe.period, hl2)
shouldInvert = f_calcShouldInvert()
depositExchangeRate = if config_depositCurrency == syminfo.currency
    // if USDUSD, no exchange of course
    1
else
    // else, USDCAD to CADUSD invert if we need
    shouldInvert ? (1 / rate) : rate

//============================================================================
// Range Edge caliculation
//============================================================================

f_calcEntryBand_high() =>
    _highest = max(open[3], close[3])
    for i = 4 to (config_entryBandBars - 1)
        _highest := max(_highest, open[i], close[i])
    _highest

f_calcEntryBand_low() =>
    _lowest = min(open[3], close[3])
    for i = 4 to (config_entryBandBars - 1)
        _lowest := min(_lowest, open[i], close[i])
    _lowest

entryBand_high = f_calcEntryBand_high()
entryBand_low = f_calcEntryBand_low()
entryBand_height = entryBand_high - entryBand_low

plot(entryBand_high, color=COLOR_ENTRY_BAND, linewidth=1)
plot(entryBand_low, color=COLOR_ENTRY_BAND, linewidth=1)

rangeBreakDetected_long = entryBand_high < close
rangeBreakDetected_short = entryBand_low > close

shouldMakeEntryLong = (strategy.position_size == 0) and rangeBreakDetected_long
shouldMakeEntryShort = (strategy.position_size == 0) and rangeBreakDetected_short

//============================================================================
// SL & Quantity
//============================================================================

var sl_long = hl2
var sl_short = hl2

entryQty = 0
slPips = 0.0

// just show info bubble
f_showEntryInfo(_isLong) =>
    _str =
      'SL pips: ' + tostring(slPips) + '\n' +
      'Qty: ' + tostring(entryQty)
    _bandHeight = entryBand_high - entryBand_low
    _y = _isLong ? (entryBand_low + _bandHeight * 1/4) : (entryBand_high - _bandHeight * 1/4)
    _style = _isLong ? label.style_label_up : label.style_label_down
    label.new(bar_index, _y, _str, size=size.large, style=_style)

if shouldMakeEntryLong
    sl_long := (entryBand_high + entryBand_low) / 2
    slPips := f_convertPriceToPips(close - sl_long)
    entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips)
if shouldMakeEntryShort
    sl_short := (entryBand_high + entryBand_low) / 2
    slPips := f_convertPriceToPips(sl_short - close)
    entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips)

// trailing SL
if strategy.position_size > 0
    sl_long := max(sl_long, entryBand_low)
if strategy.position_size < 0
    sl_short := min(sl_short, entryBand_high)

//============================================================================
// backtest duration
//============================================================================

// Calculate start/end date and time condition
startDate  = timestamp(fromYear, fromMonth, fromDay, 00, 00)
finishDate = timestamp(toYear,   toMonth,   toDay,   00, 00)

//============================================================================
// make entries
//============================================================================

if (true)
    if shouldMakeEntryLong
        strategy.entry(id="Long", long=true, stop=close, qty=entryQty)
        f_showEntryInfo(true)
    if shouldMakeEntryShort
        strategy.entry(id="Short", long=false, stop=close, qty=entryQty)
        f_showEntryInfo(false)

strategy.exit('Long-SL/TP', 'Long', stop=sl_long)
strategy.exit('Short-SL/TP', 'Short', stop=sl_short)

//============================================================================
// plot misc
//============================================================================

sl = strategy.position_size > 0 ? sl_long :
  strategy.position_size < 0 ? sl_short : na

plot(sl, color=color.red, style=plot.style_cross, linewidth=2, title="SL")

value_bgcolor = rangeBreakDetected_long ? color.green :
  rangeBreakDetected_short ? color.red : COLOR_TRANSPARENT

bgcolor(value_bgcolor, transp=95)


もっと