Chiến lược giao dịch có hệ thống hóa quy định này thuộc loại theo xu hướng. Nó sử dụng chuỗi giá được thống nhất hóa để tạo tín hiệu giao dịch, thay vì sử dụng giá cổ phiếu trực tiếp. Chiến lược này sử dụng các kỹ thuật điều chỉnh vị thế và quản lý rủi ro cao cấp, thường chỉ được sử dụng trong quản lý danh mục đầu tư của tổ chức, là bằng chứng cho việc điều chỉnh vị trí của các cố vấn giao dịch hàng hóa (CTA) và quản lý quỹ tương lai.
Thang giá thống nhất là tỷ lệ lợi nhuận hàng ngày tích lũy của giá được điều chỉnh biến động được tính dựa trên toàn bộ chuỗi thời gian giá. Thời gian cửa sổ điều chỉnh biến động được xác định bởi người dùng.
Chiến lược giao dịch này rất đơn giản, giá định nghĩa sẽ tăng lên trên đường Hull Moving Average, và giảm xuống trên đường Counter. Các tín hiệu giao dịch mới sẽ chủ động xóa bỏ các vị trí ngược cũ.
Kích thước giữ vị trí dựa trên biến động giá gần đây và mục tiêu rủi ro hàng năm được xác định bởi người dùng. Về cơ bản, kích thước vị trí được điều chỉnh theo biến động giá, giữ vị trí lớn hơn khi biến động thấp và giữ vị trí nhỏ hơn khi biến động cao.
Cài đặt Stop Loss dựa trên số nhân của biến động thực tế trung bình gần đây của giá, người dùng có thể cấu hình.
Các biện pháp kiểm soát rủi ro bao gồm sử dụng các kết hợp moving average khác nhau, điều chỉnh mục tiêu rủi ro vị trí, v.v.
Chiến lược này tích hợp nhiều rủi ro kiểm soát kỹ thuật, chẳng hạn như giá định nghĩa, hoãn chuyển động, dừng lỗ, v.v. . Sử dụng nguyên tắc theo dõi xu hướng đơn giản để giao dịch. Có thể điều chỉnh tham số để tối ưu hóa theo thị trường và tình huống cá nhân.
/*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)