该策略综合运用了指数移动平均线交叉系统和海龟交易系统两个流行的系统交易策略。该系统专门用于日线时间框架,通过动态调整仓位,实时跟踪市场趋势,具有较强的跟踪能力。
该策略包含两种子策略:趋势策略和突破策略。
趋势策略使用快速EMA和慢速EMA的交叉作为交易信号。快速EMA周期长度由用户设定,慢速EMA周期长度为快速EMA 5 倍。信号由快慢EMA差值除以252周期回报率标准差得到,经过波动率调整后产生更可靠的交易信号。当检测到新趋势形成时,做多或做空。
突破策略使用固定周期最高价和最低价的平均值作为基准线。当价格相对基准线上涨或下跌超过一定幅度时,产生做多或做空信号。
仓位调整根据最近价格波动性和用户设定的年化风险目标计算。波动性较小时仓位较大,波动性较大时仓位较小,实现风险调整后的动态仓位管理。
止损基于真实波幅的倍数设置。追踪止损基于最高价和最低价的移动 zurück收。
该策略具有以下优势:
结合趋势跟踪和突破两个子策略,可以在不同市场环境中进行适应性切换,具有较强的鲁棒性。
应用高级仓位管理和风险控制技术,可以动态调整仓位,有效控制风险。
利用真实波动性和年化风险目标调整仓位,可以在高低波动性市场中获得相对稳定的组合风险水平。
基于价格实际波动设定止损位置,可以有效避免止损离场造成不必要的小损失。
实时调整追踪止损位置,可以灵活跟踪趋势获利,及时止损离场。
该策略的主要风险在于:
依赖参数优化,不同参数对策略表现影响较大,需要进行全面测试以取得最佳参数。
追踪止损在震荡趋势中可能过于频繁止损离场。可以适当放宽止损幅度,优化止损机制。
仓位管理和风险控制技术对初始资金和交易成本较为敏感。初始资金过小和交易成本过高会影响策略盈利能力。
策略对年化风险目标和最大杠杆的设定依赖于正确评估标的波动性。波动性评估不准确可能导致仓位偏大或偏小。
该策略的主要优化方向包括:
寻找最优参数组合。可以通过更多历史数据的回测,找到最优参数设定。
改进止损机制。可以测试移动止损,时间止损,震荡止损等止损形式,优化止损策略。
优化仓位和风险管理。可以测试不同风险目标,以寻找最佳风险收益组合。还可以测试不同杠杆水平的影响。
尝试其他辅助指标。可以加入更多技术指标来提高信号的准确性和策略的稳健性。
测试不同的持仓周期。可以尝试利用更高周期辅助决策,以提高持仓配置的准确性。
该策略整合趋势跟踪和趋势突破两大类别交易策略,运用高级动态仓位管理技术,实现风险调整后的持仓配置,可以有效控制风险的同时跟踪市场走势,获利能力较强,值得进一步测试和优化。
/*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)