Name
动态调仓趋势跟踪系统Dynamic-Position-Rebalancing-Trend-Tracking-System
Author
ChaoZhang
Strategy Description
[trans]
该策略综合运用了指数移动平均线交叉系统和海龟交易系统两个流行的系统交易策略。该系统专门用于日线时间框架,通过动态调整仓位,实时跟踪市场趋势,具有较强的跟踪能力。
该策略包含两种子策略:趋势策略和突破策略。
趋势策略使用快速EMA和慢速EMA的交叉作为交易信号。快速EMA周期长度由用户设定,慢速EMA周期长度为快速EMA 5 倍。信号由快慢EMA差值除以252周期回报率标准差得到,经过波动率调整后产生更可靠的交易信号。当检测到新趋势形成时,做多或做空。
突破策略使用固定周期最高价和最低价的平均值作为基准线。当价格相对基准线上涨或下跌超过一定幅度时,产生做多或做空信号。
仓位调整根据最近价格波动性和用户设定的年化风险目标计算。波动性较小时仓位较大,波动性较大时仓位较小,实现风险调整后的动态仓位管理。
止损基于真实波幅的倍数设置。追踪止损基于最高价和最低价的移动 zurück收。
该策略具有以下优势:
-
结合趋势跟踪和突破两个子策略,可以在不同市场环境中进行适应性切换,具有较强的鲁棒性。
-
应用高级仓位管理和风险控制技术,可以动态调整仓位,有效控制风险。
-
利用真实波动性和年化风险目标调整仓位,可以在高低波动性市场中获得相对稳定的组合风险水平。
-
基于价格实际波动设定止损位置,可以有效避免止损离场造成不必要的小损失。
-
实时调整追踪止损位置,可以灵活跟踪趋势获利,及时止损离场。
该策略的主要风险在于:
-
依赖参数优化,不同参数对策略表现影响较大,需要进行全面测试以取得最佳参数。
-
追踪止损在震荡趋势中可能过于频繁止损离场。可以适当放宽止损幅度,优化止损机制。
-
仓位管理和风险控制技术对初始资金和交易成本较为敏感。初始资金过小和交易成本过高会影响策略盈利能力。
-
策略对年化风险目标和最大杠杆的设定依赖于正确评估标的波动性。波动性评估不准确可能导致仓位偏大或偏小。
该策略的主要优化方向包括:
-
寻找最优参数组合。可以通过更多历史数据的回测,找到最优参数设定。
-
改进止损机制。可以测试移动止损,时间止损,震荡止损等止损形式,优化止损策略。
-
优化仓位和风险管理。可以测试不同风险目标,以寻找最佳风险收益组合。还可以测试不同杠杆水平的影响。
-
尝试其他辅助指标。可以加入更多技术指标来提高信号的准确性和策略的稳健性。
-
测试不同的持仓周期。可以尝试利用更高周期辅助决策,以提高持仓配置的准确性。
该策略整合趋势跟踪和趋势突破两大类别交易策略,运用高级动态仓位管理技术,实现风险调整后的持仓配置,可以有效控制风险的同时跟踪市场走势,获利能力较强,值得进一步测试和优化。
||
This strategy integrates the exponential moving average crossover system and turtle trading system, two popular systematic trading strategies. It is specially designed for the daily timeframe to track market trends in real-time by dynamically managing positions.
The strategy contains two sub-strategies: trend strategy and breakout strategy.
The trend strategy uses fast EMA and slow EMA crossovers as trading signals. The fast EMA period is user-defined and the slow EMA period is 5 times of the fast EMA. The signal is generated by dividing the EMA difference by the 252-period return standard deviation, which is volatility-adjusted to produce more reliable signals. It goes long or short when detecting new trend formations.
The breakout strategy uses the average of highest high and lowest low prices over a fixed lookback period as the baseline. Long/short signals are generated when the price breaks out above/below the baseline by a certain percentage.
Position sizing is based on recent price volatility and user-defined annual risk target. Larger size is taken when volatility is low while smaller size is taken when volatility is high. This realizes dynamic position management with risk adjustment.
Hard stops are set as multiples of the average true range. Trailing stops trail recent highest high or lowest low prices.
The main advantages of this strategy include:
-
Combining trend tracking and breakout sub-strategies adapts to different market environments with strong robustness.
-
Applying advanced position sizing and risk management techniques dynamically manages position and effectively controls risk.
-
Volatility-adjusting positions based on recent volatility and annual risk target maintains relatively stable portfolio risk across high/low volatility regimes.
-
Setting stop loss based on actual price fluctuation avoids unnecessary small losses from stop runs.
-
Adjusting trailing stop in real-time flexibly follows trends to book profits and stops out timely.
The main risks of this strategy are:
-
Reliance on parameter optimization. Different parameters considerably impact strategy performance so comprehensive testing is needed to find optimum parameters.
-
Frequent stop outs in choppy trends. Stop loss width could be relaxed and stop mechanisms optimized.
-
Sensitivity to initial capital and trading costs. Insufficient initial capital and high trading costs negatively impact profitability.
-
Reliance on accurate volatility estimates for position sizing and risk controls. Inaccurate volatility estimates lead to oversized or undersized positions.
The main optimization directions include:
-
Search for optimal parameter sets via more backtesting with larger historical dataset.
-
Improve stop mechanisms by testing various stops like moving stops, time stops, volatility stops etc.
-
Optimize position sizing and risk management by testing different risk targets to find best risk-return profile. Also test impacts of different leverage levels.
-
Try more auxiliary indicators to improve signal accuracy and strategy robustness.
-
Test different holding periods by assisting decisions with higher timeframe signals to improve position allocation accuracy.
This strategy integrates two major categories of trading strategies: trend following and breakouts. By applying advanced dynamic position adjustment techniques, it effectively controls risk while tracking market moves to profit. It demonstrates strong profit potential and is worth further testing and optimization.
[/trans]
Strategy Arguments
Argument | Default | Description |
---|---|---|
v_input_1_close | 0 | (?Strategy Settings)Source: close |
v_input_int_1 | 10 | Lookback period for fast EMA |
v_input_int_2 | 20 | Lookback period for Breakout |
v_input_2 | true | (?Strategy toggle)Long |
v_input_3 | true | Short |
v_input_4 | false | Trend |
v_input_5 | true | Breakout |
v_input_float_1 | 2 | (?Risk Management Settings)Stop multiple |
v_input_int_3 | 10 | Trail lookback |
v_input_float_2 | true | Max Leverage |
v_input_float_3 | 15 | Annualised Volatility Target % |
v_input_6 | true | Compounding |
v_input_float_4 | 50 | % |
v_input_int_4 | true | (?Backtest range)From Day |
v_input_int_5 | true | From Mon |
v_input_int_6 | 2018 | From Yr |
v_input_int_7 | true | To Day |
v_input_int_8 | true | To Mon |
v_input_int_9 | 9999 | To Yr |
Source (PineScript)
/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 1h
basePeriod: 15m
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 Turtle and Trend System", shorttitle="Turtle Trend", overlay=true, slippage=10, pyramiding=1, precision = 4, calc_on_order_fills = false, calc_on_every_tick = false, default_qty_value = 0.1, initial_capital = 1000, commission_value = 0.06, process_orders_on_close = true)
// Inputs and Parameters
src = input(close, 'Source', group='Strategy Settings')
length = input.int(title="Lookback period for fast EMA", defval=10, minval=2, group='Strategy Settings', tooltip='This sets the lookback period for the fast exponential moving average. The slow EMA is 5x the fast EMA length')
blength = input.int(title="Lookback period for Breakout", defval=20, minval=5, step=5, group='Strategy Settings')
long = input(true, 'Long', inline='08', group='Strategy toggle')
short = input(true, 'Short', inline='08', group='Strategy toggle', tooltip='Toggle long/short strategy on/off')
EMAwt = input(false, 'Trend', inline='01', group='Strategy toggle')
breakwt = input(true, 'Breakout', inline='01', group='Strategy toggle', tooltip='Toggle trend/breakout strategy on/off')
stopMultiple = input.float(2, 'Stop multiple', step=0.5, group='Risk Management Settings', tooltip='Multiple for ATR, setting hard stop loss from entry price')
trail = input.int(10, 'Trail lookback', step=5, group='Risk Management Settings', tooltip='Lookback period for the trailing stop')
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(15, 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(true, '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 = time >= start and time <= finish
// Breakout strategy
lower = ta.lowest(low[1], blength)
upper = ta.highest(high[1], blength)
basis = math.avg(upper, lower)
signal = 20*(close - basis) / (upper - lower)
// Trend strategy
fEMA = ta.ema(close[1], length)
sEMA = ta.ema(close[1], length*5)
emadiff = fEMA - sEMA
nemadiff = 5*emadiff/(ta.stdev(close - close[1], 252))
//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
// Trailing stop
tlower = ta.lowest(low[1], trail)
tupper = ta.highest(high[1], trail)
tbasis = math.avg(tupper, tlower)
tsignal = 20*(close - tbasis) / (tupper - tlower)
// Strategy Rules
if EMAwt
if long
longCondition2 = (nemadiff >2 and nemadiff[1] <2) and window
exitlong = tsignal <= -10
if (longCondition2)
strategy.entry('Trend Long!', strategy.long, qty=shares)
if strategy.position_size > 0
strategy.exit('Stop Long', from_entry = 'Trend Long!', stop=(strategy.opentrades.entry_price(0) - (openN * stopMultiple)))
if (exitlong)
strategy.close('Trend Long!', immediately = true)
if short
shortCondition2 = (nemadiff <-1 and nemadiff[1] >-1) and window
exitshort = tsignal >= 10
if (shortCondition2)
strategy.entry('Trend Short!', strategy.short, qty=shares)
if strategy.position_size < 0
strategy.exit('Stop Short', from_entry = 'Trend Short!', stop=(strategy.opentrades.entry_price(0) + (openN * stopMultiple)))
if (exitshort)
strategy.close('Trend Short!', immediately = true)
if breakwt
if long
longCondition1 = (signal >= 10) and window
exitlong = tsignal <= -10
if (longCondition1)
strategy.entry('Break Long!', strategy.long, qty=shares)
if strategy.position_size > 0
strategy.exit('Stop Long', from_entry = 'Break Long!', stop=(strategy.opentrades.entry_price(0) - (openN * stopMultiple)))
if (exitlong)
strategy.close('Break Long!', immediately = true)
if short
shortCondition1 = (signal <= -10) and window
exitshort = tsignal >= 10
if (shortCondition1)
strategy.entry('Break Short!', strategy.short, qty=shares)
if strategy.position_size < 0
strategy.exit('Stop Short', from_entry = 'Break Short!', stop=(strategy.opentrades.entry_price(0) + (openN * stopMultiple)))
if (exitshort)
strategy.close('Break Short!', immediately = true)
// Visuals of trend and direction
plot(nemadiff, title='EMA Forecast', color=color.black, display=display.none)
plot(ta.sma(ta.median(math.sqrt(math.pow(nemadiff,2)), 700), 350), 'Forecast mean', color=color.rgb(245, 0, 0), display=display.none)
MAColor = fEMA > sEMA ? #00ff00 : #ff0000
MA1 = plot(fEMA, title='Fast EMA', color=MAColor)
MA2 = plot(sEMA, title='Slow EMA', color=MAColor)
fill(MA1, MA2, title='Band Filler', color=MAColor)
Detail
https://www.fmz.com/strategy/440077
Last Modified
2024-01-26 14:41:08