Đột phá với chiến lược dừng lỗ cố định


Ngày tạo: 2023-11-03 14:31:21 sửa đổi lần cuối: 2023-11-03 14:31:21
sao chép: 0 Số nhấp chuột: 638
1
tập trung vào
1621
Người theo dõi

Đột phá với chiến lược dừng lỗ cố định

Tổng quan

Ý tưởng chính của chiến lược này là sử dụng breakeven để xác định xu hướng, kết hợp với dừng cố định để quản lý rủi ro. Chiến lược này đầu tiên tính toán giá cao nhất và giá thấp nhất trong một chu kỳ nhất định, tạo ra một vùng phá vỡ.

Nguyên tắc chiến lược

Chiến lược này bao gồm bốn phần chính: quản lý vị trí, nhận diện băng thông đột phá, thiết lập dừng lỗ và tính toán số lượng.

Đầu tiên, chiến lược sẽ xác định vị trí hiện tại. Nếu đã có vị trí, không có tín hiệu mới.

Thứ hai, chiến lược sẽ tính toán giá cao nhất và giá thấp nhất trong một chu kỳ nhất định, tạo ra một vùng phá vỡ. Khi giá từ bên trong vùng phá vỡ ra bên ngoài, tạo ra tín hiệu giao dịch. Cụ thể, nếu giá phá vỡ băng giá lên đường, tạo ra tín hiệu nhiều; Nếu giá phá vỡ băng giá xuống đường, tạo ra tín hiệu trống.

Ngoài ra, khi có nhiều tín hiệu, chiến lược sẽ thiết lập điểm dừng lỗ ở giữa vùng phá vỡ. Khi có tín hiệu tháo lỗ, cũng sẽ thiết lập điểm dừng lỗ. Để theo dõi dừng lỗ, chiến lược cũng sẽ điều chỉnh điểm dừng lỗ trong thời gian thực khi giữ vị trí.

Cuối cùng, chiến lược cho phép thiết lập số tiền dừng cố định. Khi tín hiệu được tạo ra, chiến lược sẽ tính toán khoảng cách điểm dừng đến giá hiện tại, sau đó kết hợp các yếu tố như đơn vị đề nghị, tỷ giá hối đoái, tính toán số tiền đại diện cho sự thay đổi giá giữa các điểm dừng. Sau đó tính toán ngược lại số lượng giao dịch dựa trên số tiền dừng cố định.

Đây là nguyên tắc chính của chiến lược. Nhận biết xu hướng bằng cách phá vỡ và kiểm soát rủi ro bằng cách sử dụng dừng cố định.

Phân tích lợi thế

Chiến lược dừng lỗ cố định băng thông phá vỡ này có những lợi thế sau:

  1. Tư tưởng dừng lỗ tiên tiến. Chiến lược sử dụng số tiền dừng lỗ cố định thay vì khoảng cách dừng lỗ cố định. Điều này tránh được vấn đề rủi ro không thể cố định do giá trị điểm khác nhau giữa các giống khác nhau.

  2. Tính toán số lượng hợp lý. Chiến lược có thể tính toán số lượng giao dịch thông minh dựa trên số tiền dừng cố định, cho phép kiểm soát mỗi tổn thất, do đó kiểm soát hợp lý các lỗ hổng rủi ro.

  3. Nhận dạng đột phá đơn giản và hiệu quả. Phương pháp nhận dạng của băng thông đột phá đơn giản và trực tiếp, có thể xác định hướng xu hướng một cách hiệu quả. Nhận dạng băng thông đột phá như vậy có thể tránh các tín hiệu sai lệch nhiều hơn so với chỉ phá vỡ một mức giá.

  4. Theo dõi dừng lỗ tăng lợi nhuận. Chiến lược có thể điều chỉnh vị trí dừng lỗ trong thời gian thực, theo dõi dừng lỗ, giúp khóa nhiều lợi nhuận hơn.

  5. Phạm vi áp dụng rộng rãi. Chiến lược này có thể áp dụng cho bất kỳ giống nào, chỉ cần đặt các tham số tốt, bạn có thể kiểm soát rủi ro với số tiền cố định, do đó có khả năng áp dụng rất rộng rãi.

  6. Cấu trúc mã rõ ràng. Cấu trúc mã chiến lược rõ ràng, các mô-đun chức năng được giải thích tốt, dễ hiểu và tối ưu hóa sau đó.

Phân tích rủi ro

Mặc dù có những lợi thế như trên, chiến lược này vẫn có một số rủi ro cần lưu ý:

  1. Chất lượng hình dạng đột phá không thể được đánh giá. Chất lượng hình dạng đột phá không thể được đánh giá trong chiến lược, có thể tạo ra một số tín hiệu chất lượng thấp. Cần lọc kết hợp với các chỉ số khác.

  2. Hạn chế cố định có thể quá cơ học. Giá thị trường thường có đặc điểm của hành động nhảy vọt, Hạn chế cố định có thể quá phụ thuộc vào quy tắc và không thể điều chỉnh linh hoạt.

  3. Không giới hạn tần suất giao dịch. Chiến lược không giới hạn tần suất giao dịch, có thể xuất hiện quá thường xuyên. Cần kết hợp với các quy tắc khác để giới hạn tần suất.

  4. Cài đặt các tham số phụ thuộc vào dừng cố định. Việc thiết lập số lỗ hổng cố định liên quan đến kiểm soát lỗ hổng tổng thể, cần thiết phải được thiết lập hợp lý theo nhiều khía cạnh khác nhau như quy mô vốn, sở thích rủi ro.

  5. Hướng phá vỡ có thể tạo ra tín hiệu sai. Khi có sự biến động hoặc điều chỉnh giá, tín hiệu phá vỡ có thể bị lỗi. Cần kết hợp nhiều điều kiện để tối ưu hóa.

  6. Thiếu thiết lập điểm dừng. Chiến lược hiện không có cơ chế dừng, không thể chủ động xác định lợi nhuận. Điều này có thể dẫn đến lợi nhuận không mong muốn.

Đối với những rủi ro trên, chúng ta có thể tối ưu hóa theo các cách sau:

  1. Thêm các chỉ số để đánh giá hình dạng, lọc chất lượng tín hiệu. Ví dụ: MACD, KD, v.v.

  2. Kết hợp các chỉ số cường độ đột phá để đánh giá chất lượng đột phá. Ví dụ: đánh giá sự mạnh mẽ của đột phá bằng cách thay đổi khối lượng giao dịch.

  3. Tăng giới hạn tần suất mở vị trí. Ví dụ: chỉ giao dịch một lần mỗi ngày hoặc các quy tắc tương tự.

  4. Tối ưu hóa logic thiết lập dừng cố định. Ví dụ: thay đổi dừng phần trăm theo giá trị thềm cụ thể.

  5. Thêm các điều kiện lọc khác, chẳng hạn như tăng cường dừng lỗ, tỷ lệ biến động giá.

  6. Thêm chiến lược dừng. Ví dụ: dừng khi gần điểm kháng.

Hướng tối ưu hóa

Theo phân tích trên, chiến lược này có thể được tối ưu hóa theo các khía cạnh sau:

  1. Tăng điều kiện lọc, cải thiện chất lượng tín hiệu. Có thể thêm nhiều chỉ số kỹ thuật, đánh giá chất lượng xu hướng, tránh tín hiệu đột phá không mong muốn. Cũng có thể đánh giá cường độ đột phá.

  2. Tối ưu hóa chiến lược dừng lỗ, giúp nó linh hoạt hơn. Bạn có thể thay đổi dừng lỗ theo tỷ lệ sau khi vượt qua một khoảng cách nhất định. Bạn cũng có thể tối ưu hóa khoảng cách dừng lỗ theo tỷ lệ dao động trong thời gian thực.

  3. Kiểm soát tần suất giao dịch, tránh giao dịch quá mức. Bạn có thể đặt các điều kiện lọc theo khoảng thời gian hoặc số lần, giảm tần suất giao dịch.

  4. Kết hợp các chỉ số đánh giá xu hướng, thay đổi thời gian lựa chọn vào sân. Ví dụ: tối ưu hóa để vào sân sau khi xác nhận xu hướng.

  5. Tối ưu hóa chiến lược dừng và tăng khả năng lợi nhuận. Bạn có thể đặt mục tiêu lợi nhuận, di chuyển dừng, dừng biến động và nhiều cách khác.

  6. Thiết lập các tham số rủi ro tối ưu. Bạn có thể thiết lập các tham số tốt hơn dựa trên kết quả kiểm tra lại, chẳng hạn như số tiền dừng cố định, chu kỳ phá vỡ, v.v.

  7. Cải thiện cấu trúc mã, tăng khả năng mở rộng. Giải mã thêm các mô-đun như tạo tín hiệu, lọc, điều khiển gió, và lợi nhuận.

  8. Thử nghiệm nhiều hơn nữa các loại của không gian đấu giá. Đánh giá lợi thế của đấu giá của các loại khác nhau của sự kết hợp.

Bằng cách tối ưu hóa nhiều mặt trên, có thể tăng cường hơn nữa sự ổn định và khả năng sinh lợi của chiến lược dừng lỗ đột phá này. Đồng thời xây dựng nền tảng cho việc mở rộng sang nhiều danh mục chiến lược khác trong tương lai.

Tóm tắt

Chiến lược tổng thể là hợp lý, sử dụng các xu hướng nhận diện băng thông đột phá, và sử dụng số tiền cố định dừng để kiểm soát rủi ro. Điều này có tính tiên tiến về quản lý rủi ro. Đồng thời, tính toán số lượng giao dịch cũng là một cách hợp lý, có thể kiểm soát mỗi tổn thất. Nhưng chiến lược có thể được tối ưu hóa bằng nhiều phương tiện để cải thiện chất lượng tín hiệu, linh hoạt của chiến lược dừng lỗ và lợi nhuận.

Mã nguồn chiến lược
/*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)