Strategi Dagangan Momentum yang Disesuaikan dengan Risiko Dinamik

Penulis:ChaoZhang, Tarikh: 2024-01-24 11:13:39
Tag:

img

Ringkasan

Strategi dagangan berasaskan peraturan yang unik ini adalah dalam trend kategori berikut. Ia menggunakan siri harga biasa yang diubah dari harga ticker mentah ke isyarat dagangan yang dihasilkan. Teknik pengukuran kedudukan dan pengurusan risiko lanjutan, yang biasanya dikhaskan untuk pengurusan portfolio institusi, digunakan dalam strategi ini - teknologi pengendalian kedudukan dan risiko yang terbukti yang digunakan oleh penasihat kewangan seperti Penasihat Dagangan Komoditi dan dana niaga hadapan yang dikendalikan.

Mekanik Strategi

harga normal adalah siri pulangan harian terkumpul yang diselaraskan dengan turun naik. Penampakan semula penyesuaian turun naik harian ditakrifkan oleh pengguna. Purata bergerak Hull harga normal digunakan sebagai penunjuk trend utama. Tempoh penampakan balik HMA juga ditakrifkan oleh pengguna, dengan tempoh lalai 100 hari untuk isyarat responsif tanpa menyebabkan perdagangan berlebihan.

Perdagangan teras adalah mudah, panjang apabila harga crossover HMA yang normal, pendek apabila crossunder HMA. isyarat baru menutup mana-mana kedudukan yang bertentangan yang sedia ada.

Saiz kedudukan diselaraskan secara dinamik berdasarkan turun naik harga baru-baru ini dan sasaran risiko tahunan yang ditakrifkan oleh pengguna. Posisi ditimbang risiko, saiz yang lebih besar dengan turun naik yang lebih rendah dan lebih kecil dengan turun naik yang lebih tinggi. Volatiliti baru-baru ini adalah penyimpangan standard pulangan selama 14 tempoh terakhir, kemudian diekstrapolasi ke dalam turun naik tahunan sebagai pulangan yang dijangkakan. Sasaran risiko tahunan digunakan sebagai rujukan untuk ukuran kedudukan yang diselaraskan dengan turun naik. Sasaran lalai adalah 10% daripada jumlah modal. Modal awal harus ditetapkan sebagai kerugian maksimum setiap perdagangan. Leverage maksimum membolehkan mencapai sasaran risiko jika turun naik semula jadi yang mendasari tidak mencukupi, dan mengurangkan turun naik yang terlalu rendah.

Hentian keras adalah berdasarkan pengganda julat sebenar purata harga baru-baru ini, boleh dikonfigurasikan oleh pengguna.

Kelebihan

  • Harga normal mengurangkan isyarat palsu
  • Kawal saiz kedudukan dinamik risiko berkesan
  • Perhentian keras menghalang kerugian melarikan diri
  • Trend mudah mengikut logik ketelusan

Risiko

  • Masalah kelewatan dengan purata bergerak Hull
  • Mengekalkan keuntungan sambil mengurangkan risiko melalui saiz kedudukan yang disesuaikan dengan turun naik
  • Stop terlalu ketat terdedah kepada paku

Langkah-langkah kawalan risiko termasuk pilihan purata bergerak alternatif, menyesuaikan sasaran risiko.

Peningkatan

  • Keberkesanan ujian jenis purata bergerak lain
  • Mengoptimumkan parameter purata bergerak
  • Cuba varian panjang atau pendek sahaja
  • Julat kehilangan berhenti tune halus
  • Percubaan dengan mekanisme stop loss yang lain

Kesimpulan

Strategi ini mengintegrasikan pelbagai teknik seperti normalisasi, pelarasan kedudukan dinamik, hentian keras untuk mengawal risiko. Dagangan berdasarkan peraturan trend berikut yang mudah. Parameter boleh diselaraskan untuk pilihan peribadi dan rejimen pasaran. Layak ujian dan pengesahan lanjut untuk aplikasi dunia nyata yang berdaya maju.


/*backtest
start: 2023-01-17 00:00:00
end: 2024-01-23 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/
// © Crunchster1

//@version=5
strategy(title="Crunchster's Normalised Trend Strategy", shorttitle="Normalised Trend Strategy", overlay=false )

// Inputs and Parameters
src = input(close, 'Source', group='Strategy Settings')
length = input.int(title="Lookback period for price normalisation filter", defval=14, minval=2, group='Strategy Settings', tooltip='This sets the lookback period for the volatility adjustment of returns, which is used to transform the price series into the "real price"')
hlength = input.int(title="Lookback period for Hull Moving Average", defval=100, minval=2, group='Strategy Settings')
offset = input.int(title="HMA Offset", defval=0, minval=0, group='Strategy Settings')
long = input(true, 'Long', inline='08', group='Strategy Settings')
short = input(true, 'Short', inline='08', group='Strategy Settings', tooltip='Toggle long/short strategy on/off')

stopMultiple = input.float(1, 'Stop multiple', step=0.25, group='Risk Management Settings', tooltip='Multiple for ATR, setting hard stop loss from entry price')
lev = input.float(1, 'Max Leverage', step=0.5, group='Risk Management Settings', tooltip='Max leverage sets maximum allowable leverage of total capital (initial capital + any net profit), capping maximum volatility adjusted position size')
riskT = input.float(10, maxval=75, title='Annualised Volatility Target %', group='Risk Management Settings', tooltip='Specify annual risk target, used to determine volatility adjusted position size. Annualised daily volatility is referenced to this value and position size adjusted accordingly')
comp = input(false, 'Compounding', inline='09', group='Risk Management Settings')
Comppct = input.float(50, '%', step=5, inline='09', group='Risk Management Settings', tooltip='Toggle compounding of profit, and set % of profit to compound')

// Backtesting period
FromDay = input.int(defval=1, title='From Day', minval=1, maxval=31, inline='04', group='Backtest range')
FromMonth = input.int(defval=1, title='From Mon', minval=1, maxval=12, inline='04', group='Backtest range')
FromYear = input.int(defval=2018, title='From Yr', minval=1900, inline='04', group='Backtest range', tooltip='Set start of backtesting period')
ToDay = input.int(defval=1, title='To Day', minval=1, maxval=31, inline='05', group='Backtest range')
ToMonth = input.int(defval=1, title='To Mon', minval=1, maxval=12, inline='05', group='Backtest range')
ToYear = input.int(defval=9999, title='To Yr', minval=1900, inline='05', group='Backtest range', tooltip='Set end of backtesting period')

start = timestamp(FromYear, FromMonth, FromDay, 00, 00)
finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)
window = true

// Normalised returns calculation
nRet = (src - src[1]) / ta.stdev((src - src[1]), length)

nPrice = ta.cum(nRet)

//Hull Moving Average - using normalised price series
fHMA = ta.wma(2 * ta.wma(nPrice[offset], hlength / 2) - ta.wma(nPrice[offset], hlength), math.round(math.sqrt(hlength)))

//Risk Management formulae
strategy.initial_capital = 50000
tr = math.max(high - low, math.abs(high - close), math.abs(low - close)) //True range
stopL = ta.sma(tr, 14) //Average true range
stdev = ta.stdev(close-close[1], 14) //volatility of recent returns
maxcapital = strategy.initial_capital+strategy.netprofit //Maximum capital available to invest - initial capital net of profit
annvol = 100*math.sqrt(365)*stdev/close //converts recent volatility of returns into annualised volatility of returns - assumes daily timeframe

risk = 1.1
if comp
    risk := (strategy.initial_capital+(Comppct*strategy.netprofit/100))//adjust investment capital to include compounding
else
    risk := strategy.initial_capital

shares = (risk * (riskT/annvol)) / close //calculates volatility adjusted position size, dependent on user specified annualised risk target
if ((shares*close) > lev*maxcapital) //ensures position size does not exceed available capital multiplied by user specified maximum leverage
    shares := lev*maxcapital/close

//To set the price at the entry point of trade
Posopen() =>
    math.abs(strategy.position_size[1]) <= 0 and math.abs(strategy.position_size) > 0

var float openN = na
if Posopen()
    openN := stopL

// Strategy Rules
if long
    longCondition = ta.crossover(nPrice, fHMA) and window
    exitlong = ta.crossunder(nPrice, fHMA)
    if (longCondition)
        strategy.entry('Go Long!', strategy.long, qty=shares)
    if strategy.position_size > 0    
        strategy.exit('Stop Long', from_entry = 'Go Long!', stop=(strategy.opentrades.entry_price(0) - (openN * stopMultiple)))
    if (exitlong)
        strategy.close('Go Long!', immediately = true)

if short
    shortCondition = ta.crossunder(nPrice, fHMA) and window
    exitshort = ta.crossover(nPrice, fHMA)
    if (shortCondition)
        strategy.entry('Go Short!', strategy.short, qty=shares)
    if strategy.position_size < 0   
        strategy.exit('Stop Short', from_entry = 'Go Short!', stop=(strategy.opentrades.entry_price(0) + (openN * stopMultiple)))
    if (exitshort)
        strategy.close('Go Short!', immediately = true)

// Visuals of trend and direction
plot(nPrice, title='Real Price', color=color.black)

MAColor = fHMA > fHMA[3] ? #00ff00 : #ff0000
MA1 = plot(fHMA, title='Hull MA', color=MAColor)
MA2 = plot(fHMA[3], title='Hull MA Offset', color=MAColor)
fill(MA1, MA2, title='Band Filler', color=MAColor)

Lebih lanjut