固定ストップロス戦略によるブレイクアウト


作成日: 2023-11-03 14:31:21 最終変更日: 2023-11-03 14:31:21
コピー: 0 クリック数: 399
1
フォロー
1224
フォロワー

固定ストップロス戦略によるブレイクアウト

概要

この戦略の主な考えは,ブレイクバンドを活用してトレンドの方向性を認識し,固定ストップと組み合わせてリスク管理を行うことである.戦略は,まず,一定の周期内の最高価格と最低価格を計算して,ブレイクバンドを形成する.価格がブレイクバンドを破るとき,取引シグナルを生成する.さらに,戦略は,トレーダーに固定ストップの金額を設定することを許可する.

戦略原則

この戦略は主に4つの部分から構成される:ポジション管理,突破帯の識別,ストップ損失設定,数量計算.

まず,戦略は,現在ポジションを持っているかどうかを判断します. ポジションを持っている場合は,新しい信号は生成されません.

次に,戦略は,一定周期内の最高価格と最低価格を計算し,突破帯を形成する. 価格が突破帯の内から外へ突破するときは,取引信号を生成する. 具体的には,価格が突破帯を突破して上線する場合は,多信号を生成する.

さらに,多信号が生じる場合,戦略は突破帯の真ん中点をストップポイントとして設定する.空調信号が生じる場合,ストップポイントも設定する.ストップを追跡するために,戦略は,ポジションの期間中にストップポイントをリアルタイムで調整する.

最後に,戦略は,固定ストップの金額を設定することを許可します.信号が生じると,戦略は,ストップのポイントから現在の価格までの点数距離を計算し,代価単位,為替レートなどの要因を組み合わせて,ストップのポイント間の価格変化が代表する金額を計算します.そして,固定ストップに基づいて取引数を逆算します.

これは戦略の主要な原則である. 突破帯のトレンドの方向性を認識し,固定ストップを活用してリスク管理を行うことが,戦略の核心思想である.

優位分析

破盤帯の固定ストップには以下の利点があります.

  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)