0bps

Strategy vault / Trend following

Multi Trend Crossover Strategy

This strategy selects two different trend indicators, fast and slow, and goes long when the fast trend crosses the slow trend, and goes short when it crosses below, to generate trading signals. The strategy has more…

Author
ChaoZhang
Complexity
Advanced · 333 lines
Parameters
21
Backtest bar
3h · intraday
Tested on
BTC/USDT · futures

Overview

This strategy selects two different trend indicators, fast and slow, and goes long when the fast trend crosses the slow trend, and goes short when it crosses below, to generate trading signals. The strategy has more than 20 different trend calculation methods built-in, and users can freely combine and choose.

Strategy Principle

The core of this strategy is the selection and combination of fast trend indicators and slow trend indicators:

FastTrend = Fast trend indicator selected by the user
SlowTrend = Slow trend indicator selected by the user

Fast trend indicators include SMA, EMA, KAMA, and over 20 other trend algorithms; slow indicators can also be freely selected.

Trading signal generation determines the relationship between fast and slow trends:

if FastTrend > SlowTrend:
    go long
if FastTrend < SlowTrend:  
    Close Position

The long signal is generated when the fast trend crosses above the slow trend, and the short signal is generated when the fast trend crosses below the slow trend.

Advantage Analysis

  • Built-in more than 20 indicators can be freely combined, highly flexible
  • Able to identify trend situations in different time periods
  • The best indicator combination can be found through parameter optimization
  • Can be long and short at the same time to capture the two-way trend
  • Adjustable stop-loss strategy to control risk

Risk Analysis

  • Improper selection of fast and slow trend indicators may fail
  • Trend indicators lag, may miss the best entry point
  • Easy to generate false signals in a ranging market
  • Need to optimize parameters to find the best combination of indicators
  • Cannot stop loss quickly, there is a risk of increasing losses

Optimization Direction

This strategy can be optimized from the following aspects:

  1. Adjust indicators and parameters of fast and slow trends to find the best combination.

  2. Add Filtering Conditions: Avoid generating false signals in ranging markets, for example by adding trading volume filters.

  3. Add stop loss strategies, such as trailing stop, trailing stop, etc. Control single loss.

  4. Combine with other indicators such as MACD and KDJ to improve strategy stability.

  5. Optimize the timing of entry, don't just rely on trend indicators for cross entry.

Summary

The multi-trend crossover strategy can identify trend changes in different time periods by combining fast and slow trend indicators. However, this strategy is sensitive to market fluctuations and is only suitable for market environments with obvious trends. We need to improve the stability and profitability of the strategy through parameter optimization, risk control and other means.

||

Overview

This strategy generates trading signals by selecting fast and slow trend indicators and going long when the fast trend crosses over the slow trend, and going short when the fast trend crosses below the slow trend. The strategy incorporates over 20 different trend calculations to choose from.

Strategy Logic

The core of the strategy is the selection and combination of fast and slow trend indicators:

FastTrend = User selected fast trend indicator
SlowTrend = User selected slow trend indicator

Fast trend includes SMA, EMA, KAMA and 20+ trend algorithms. Slow trend can also be freely selected.

Trading signals are generated by judging the relationship between fast and slow trends:

if FastTrend > SlowTrend:
    Go long
if FastTrend < SlowTrend:
    Close position

Long signal is triggered when fast trend crosses over slow trend. Short signal is triggered when fast trend crosses below slow trend.

Advantage Analysis

  • Incorporates 20+ indicators for flexible combinations
  • Can identify trends over different timeframes
  • Parameters can be optimized to find best combination
  • Can go both long and short to capture trends in both directions
  • Stop loss can be used to control risk

Risk Analysis

  • Wrong fast/slow trend selection may cause strategy failure
  • Trend indicators have lags, may miss best entry points
  • Prone to generating false signals in ranging markets
  • Need parameter optimization to find best indicator combinations
  • Unable to quickly cut losses, risks of letting losses run

Optimization Directions

The strategy can be improved in the following aspects:

  1. Adjust fast/slow trends and parameters to find optimal combinations.

  2. Add filters like volume to avoid false signals during market choppiness.

  3. Incorporate stop loss strategies like trailing stop loss to control single trade loss.

  4. Combine with other indicators like MACD, KDJ to improve stability.

  5. Optimize entry timing, don't just rely on trend crossover.

Summary

The multi trend crossover strategy identifies trend changes across timeframes by combining fast and slow trends. But it is sensitive to market fluctuations and only works well in obvious trending markets. We need methods like parameter optimization and risk management to improve strategy stability and profitability.

Parameters

NameDefaultWhat it controls
v_input_1timestamp(01 Jan 2000 05:00 +0000)(?Date Range)Start Time
v_input_2timestamp(01 Jan 2099 00:00 +0000)End Time
v_input_string_10(?Core Settings)Fast Trend Selector: EMA | DEMA | DSMA | ALMA | HMA | JMA | KAMA | Linear Regression (LSMA) | RMA | SMA | SMMA | Price Source | TEMA | TMA | VAMA | VIDYA | VMA | VWMA | WMA | WWMA | ZLEMA
v_input_string_20Slow Trend Selector: EMA | DEMA | DSMA | ALMA | HMA | JMA | KAMA | Linear Regression (LSMA) | RMA | SMA | SMMA | Price Source | TEMA | TMA | VAMA | VIDYA | VMA | VWMA | WMA | WWMA | ZLEMA
v_input_source_1_close0Price Source: close | high | low | open | hl2 | hlc3 | hlcc4 | ohlc4
v_input_int_110Fast Trend Length
v_input_int_2200Slow Trend Length
v_input_int_3trueLine Width
v_input_bool_1trueModel Long Trades
v_input_bool_2falseModel Short Trades
v_input_float_10.85(?Individual Trend Settings)ALMA Offset
v_input_float_26ALMA Sigma
v_input_float_33ATR Multiplier For SuperTrend
v_input_int_412ATR Length For SuperTrend
v_input_int_520DSMA Super Smoother Filter Length
v_input_int_60DSMA Super Smoother Filter Poles: 2 | 3
v_input_int_72JMA Power Parameter
v_input_int_8-45JMA Phase Parameter
v_input_float_43KAMA's Alpha
v_input_int_9falseLinear Regression Offset
v_input_int_1012VAMA Volatility lookback

Source Pine Script

/*backtest
start: 2023-08-21 00:00:00
end: 2023-09-20 00:00:00
period: 3h
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/
// @version=5
// Author = TradeAutomation


strategy(title="Multi Trend Cross Strategy Template", shorttitle="Multi Trend Cross Strategy", process_orders_on_close=true, overlay=true, commission_type=strategy.commission.cash_per_contract, commission_value=0.0035, initial_capital = 1000000, default_qty_type=strategy.percent_of_equity, default_qty_value=100)


// Backtest Date Range Inputs // 
StartTime = input(defval=timestamp('01 Jan 2000 05:00 +0000'), group="Date Range", title='Start Time')
EndTime = input(defval=timestamp('01 Jan 2099 00:00 +0000'), group="Date Range", title='End Time')
InDateRange = true

// Trend Selector //
TrendSelectorInput = input.string(title="Fast Trend Selector", defval="EMA", group="Core Settings", options=["ALMA", "DEMA", "DSMA", "EMA", "HMA", "JMA", "KAMA", "Linear Regression (LSMA)", "RMA", "SMA", "SMMA", "Price Source", "TEMA", "TMA", "VAMA", "VIDYA", "VMA", "VWMA", "WMA", "WWMA", "ZLEMA"], tooltip="Select your fast trend")
TrendSelectorInput2 = input.string(title="Slow Trend Selector", defval="EMA", group="Core Settings", options=["ALMA", "DEMA", "DSMA", "EMA", "HMA", "JMA", "KAMA", "Linear Regression (LSMA)", "RMA", "SMA", "SMMA", "Price Source", "TEMA", "TMA", "VAMA", "VIDYA", "VMA", "VWMA", "WMA", "WWMA", "ZLEMA"], tooltip="Select your slow trend")
src = input.source(close, "Price Source", group="Core Settings", tooltip="This is the price source being used for the trends to calculate based on")
length = input.int(10, "Fast Trend Length", group="Core Settings", step=5, tooltip="A long is entered when the selected fast trend crosses over the selected slow trend")
length2 = input.int(200, "Slow Trend Length", group="Core Settings", step=5, tooltip="A long is entered when the selected fast trend crosses over the selected slow trend")
LineWidth = input.int(1, "Line Width", group="Core Settings", tooltip="This is the width of the line plotted that represents the selected trend")

// Individual Moving Average / Regression Setting //
AlmaOffset = input.float(0.85, "ALMA Offset", group="Individual Trend Settings", tooltip="This only applies when ALMA is selected")
AlmaSigma = input.float(6, "ALMA Sigma", group="Individual Trend Settings", tooltip="This only applies when ALMA is selected")
ATRFactor = input.float(3, "ATR Multiplier For SuperTrend", group="Individual Trend Settings", tooltip="This only applies when SuperTrend is selected")
ATRLength = input.int(12, "ATR Length For SuperTrend", group="Individual Trend Settings", tooltip="This only applies when SuperTrend is selected")
ssfLength = input.int(20, "DSMA Super Smoother Filter Length", minval=1, tooltip="This only applies when EDSMA is selected", group="Individual Trend Settings")
ssfPoles = input.int(2, "DSMA Super Smoother Filter Poles", options=[2, 3], tooltip="This only applies when EDSMA is selected", group="Individual Trend Settings")
JMApower = input.int(2, "JMA Power Parameter", group="Individual Trend Settings", tooltip="This only applies when JMA is selected")
phase = input.int(-45, title="JMA Phase Parameter", step=10, minval=-110, maxval=110, group="Individual Trend Settings", tooltip="This only applies when JMA is selected")
KamaAlpha = input.float(3, "KAMA's Alpha", minval=1,step=0.5, group="Individual Trend Settings", tooltip="This only applies when KAMA is selected")
LinRegOffset = input.int(0, "Linear Regression Offset", group="Individual Trend Settings", tooltip="This only applies when Linear Regression is selected")
VAMALookback =input.int(12, "VAMA Volatility lookback", group="Individual Trend Settings", tooltip="This only applies when VAMA is selected")


// Trend Indicators With Library Functions //
ALMA = ta.alma(src, length, AlmaOffset, AlmaSigma) 
EMA = ta.ema(src, length)
HMA = ta.hma(src, length)
LinReg = ta.linreg(src, length, LinRegOffset)
RMA = ta.rma(src, length)
SMA = ta.sma(src, length)
VWMA = ta.vwma(src, length)
WMA = ta.wma(src, length)

ALMA2 = ta.alma(src, length2, AlmaOffset, AlmaSigma) 
EMA2 = ta.ema(src, length2)
HMA2 = ta.hma(src, length2)
LinReg2 = ta.linreg(src, length2, LinRegOffset)
RMA2 = ta.rma(src, length2)
SMA2 = ta.sma(src, length2)
VWMA2 = ta.vwma(src, length2)
WMA2 = ta.wma(src, length2)

// Additional Trend Indicators Built In And/Or Open Sourced //
//DEMA
de1 = ta.ema(src, length)
de2 = ta.ema(de1, length)
DEMA = 2 * de1 - de2

de3 = ta.ema(src, length2)
de4 = ta.ema(de3, length2)
DEMA2 = 2 * de3 - de4

// Ehlers Deviation-Scaled Moving Average - DSMA [Everget]
PI = 2 * math.asin(1)
get2PoleSSF(src, length) =>
    arg = math.sqrt(2) * PI / length
    a1 = math.exp(-arg)
    b1 = 2 * a1 * math.cos(arg)
    c2 = b1
    c3 = -math.pow(a1, 2)
    c1 = 1 - c2 - c3
    var ssf = 0.0
    ssf := c1 * src + c2 * nz(ssf[1]) + c3 * nz(ssf[2])
get3PoleSSF(src, length) =>
    arg = PI / length
    a1 = math.exp(-arg)
    b1 = 2 * a1 * math.cos(1.738 * arg)
    c1 = math.pow(a1, 2)
    coef2 = b1 + c1
    coef3 = -(c1 + b1 * c1)
    coef4 = math.pow(c1, 2)
    coef1 = 1 - coef2 - coef3 - coef4
    var ssf = 0.0
    ssf := coef1 * src + coef2 * nz(ssf[1]) + coef3 * nz(ssf[2]) + coef4 * nz(ssf[3])
zeros = src - nz(src[2])
avgZeros = (zeros + zeros[1]) / 2
// Ehlers Super Smoother Filter 
ssf = ssfPoles == 2
     ? get2PoleSSF(avgZeros, ssfLength)
     : get3PoleSSF(avgZeros, ssfLength)
// Rescale filter in terms of Standard Deviations
stdev = ta.stdev(ssf, length)
scaledFilter = stdev != 0
     ? ssf / stdev
     : 0
alpha1 = 5 * math.abs(scaledFilter) / length
EDSMA = 0.0
EDSMA := alpha1 * src + (1 - alpha1) * nz(EDSMA[1])

get2PoleSSF2(src, length2) =>
    arg = math.sqrt(2) * PI / length2
    a1 = math.exp(-arg)
    b1 = 2 * a1 * math.cos(arg)
    c2 = b1
    c3 = -math.pow(a1, 2)
    c1 = 1 - c2 - c3
    var ssf2 = 0.0
    ssf2 := c1 * src + c2 * nz(ssf2[1]) + c3 * nz(ssf2[2])
get3PoleSSF2(src, length2) =>
    arg = PI / length2
    a1 = math.exp(-arg)
    b1 = 2 * a1 * math.cos(1.738 * arg)
    c1 = math.pow(a1, 2)
    coef2 = b1 + c1
    coef3 = -(c1 + b1 * c1)
    coef4 = math.pow(c1, 2)
    coef1 = 1 - coef2 - coef3 - coef4
    var ssf2 = 0.0
    ssf2 := coef1 * src + coef2 * nz(ssf2[1]) + coef3 * nz(ssf2[2]) + coef4 * nz(ssf2[3])
// Ehlers Super Smoother Filter 
ssf2 = ssfPoles == 2
     ? get2PoleSSF2(avgZeros, ssfLength)
     : get3PoleSSF2(avgZeros, ssfLength)
// Rescale filter in terms of Standard Deviations
stdev2 = ta.stdev(ssf2, length2)
scaledFilter2 = stdev2 != 0
     ? ssf2 / stdev2
     : 0
alpha12 = 5 * math.abs(scaledFilter2) / length2
EDSMA2 = 0.0
EDSMA2 := alpha12 * src + (1 - alpha12) * nz(EDSMA2[1])

//JMA [Everget]
phaseRatio = phase < -100 ? 0.5 : phase > 100 ? 2.5 : phase / 100 + 1.5
beta = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
alpha = math.pow(beta, JMApower)
var JMA = 0.0
var e0 = 0.0
e0 := (1 - alpha) * src + alpha * nz(e0[1])
var e1 = 0.0
e1 := (src - e0) * (1 - beta) + beta * nz(e1[1])
var e2 = 0.0
e2 := (e0 + phaseRatio * e1 - nz(JMA[1])) * math.pow(1 - alpha, 2) + math.pow(alpha, 2) * nz(e2[1])
JMA := e2 + nz(JMA[1])

beta2 = 0.45 * (length2 - 1) / (0.45 * (length2 - 1) + 2)
alpha2 = math.pow(beta2, JMApower)
var JMA2 = 0.0
var e02 = 0.0
e02 := (1 - alpha2) * src + alpha2 * nz(e02[1])
var e12 = 0.0
e12 := (src - e02) * (1 - beta2) + beta2 * nz(e12[1])
var e22 = 0.0
e22 := (e02 + phaseRatio * e12 - nz(JMA2[1])) * math.pow(1 - alpha2, 2) + math.pow(alpha2, 2) * nz(e22[1])
JMA2 := e22 + nz(JMA2[1])

//KAMA [Everget]
var KAMA = 0.0
fastAlpha = 2.0 / (KamaAlpha + 1)
slowAlpha = 2.0 / 31
momentum = math.abs(ta.change(src, length))
volatility = math.sum(math.abs(ta.change(src)), length)
efficiencyRatio = volatility != 0 ? momentum / volatility : 0
smoothingConstant = math.pow((efficiencyRatio * (fastAlpha - slowAlpha)) + slowAlpha, 2)
KAMA := nz(KAMA[1], src) + smoothingConstant * (src - nz(KAMA[1], src))

var KAMA2 = 0.0
momentum2 = math.abs(ta.change(src, length2))
volatility2 = math.sum(math.abs(ta.change(src)), length2)
efficiencyRatio2 = volatility2 != 0 ? momentum2 / volatility2 : 0
smoothingConstant2 = math.pow((efficiencyRatio2 * (fastAlpha - slowAlpha)) + slowAlpha, 2)
KAMA2 := nz(KAMA2[1], src) + smoothingConstant2 * (src - nz(KAMA2[1], src))

//SMMA
var SMMA = 0.0
SMMA := na(SMMA[1]) ? ta.sma(src, length) : (SMMA[1] * (length - 1) + src) / length

var SMMA2 = 0.0
SMMA2 := na(SMMA2[1]) ? ta.sma(src, length2) : (SMMA2[1] * (length2 - 1) + src) / length2

//TEMA
t1 = ta.ema(src, length)
t2 = ta.ema(t1, length)
t3 = ta.ema(t2, length)
TEMA = 3 * (t1 - t2) + t3

t12 = ta.ema(src, length2)
t22 = ta.ema(t12, length2)
t32 = ta.ema(t22, length2)
TEMA2 = 3 * (t12 - t22) + t32

//TMA
TMA = ta.sma(ta.sma(src, math.ceil(length / 2)), math.floor(length / 2) + 1)

TMA2 = ta.sma(ta.sma(src, math.ceil(length2 / 2)), math.floor(length2 / 2) + 1)

//VAMA [Duyck]
mid=ta.ema(src,length)
dev=src-mid
vol_up=ta.highest(dev,VAMALookback)
vol_down=ta.lowest(dev,VAMALookback)
VAMA = mid+math.avg(vol_up,vol_down)

mid2=ta.ema(src,length2)
dev2=src-mid2
vol_up2=ta.highest(dev2,VAMALookback)
vol_down2=ta.lowest(dev2,VAMALookback)
VAMA2 = mid2+math.avg(vol_up2,vol_down2)

//VIDYA [KivancOzbilgic]
var VIDYA=0.0
VMAalpha=2/(length+1)
ud1=src>src[1] ? src-src[1] : 0
dd1=src<src[1] ? src[1]-src : 0
UD=math.sum(ud1,9)
DD=math.sum(dd1,9)
CMO=nz((UD-DD)/(UD+DD))
VIDYA := na(VIDYA[1]) ? ta.sma(src, length) : nz(VMAalpha*math.abs(CMO)*src)+(1-VMAalpha*math.abs(CMO))*nz(VIDYA[1])

var VIDYA2=0.0
VMAalpha2=2/(length2+1)
ud12=src>src[1] ? src-src[1] : 0
dd12=src<src[1] ? src[1]-src : 0
UD2=math.sum(ud12,9)
DD2=math.sum(dd12,9)
CMO2=nz((UD2-DD2)/(UD2+DD2))
VIDYA2 := na(VIDYA2[1]) ? ta.sma(src, length2) : nz(VMAalpha2*math.abs(CMO2)*src)+(1-VMAalpha2*math.abs(CMO2))*nz(VIDYA2[1])

//VMA [LazyBear]
sc = 1/length
pdm = math.max((src - src[1]), 0)
mdm = math.max((src[1] - src), 0)
var pdmS = 0.0
var mdmS = 0.0
pdmS := ((1 - sc)*nz(pdmS[1]) + sc*pdm)
mdmS := ((1 - sc)*nz(mdmS[1]) + sc*mdm)
s = pdmS + mdmS
pdi = pdmS/s
mdi = mdmS/s
var pdiS = 0.0
var mdiS = 0.0
pdiS := ((1 - sc)*nz(pdiS[1]) + sc*pdi)
mdiS := ((1 - sc)*nz(mdiS[1]) + sc*mdi)
d = math.abs(pdiS - mdiS)
s1 = pdiS + mdiS
var iS = 0.0
iS := ((1 - sc)*nz(iS[1]) + sc*d/s1)
hhv = ta.highest(iS, length) 
llv = ta.lowest(iS, length) 
d1 = hhv - llv
vi = (iS - llv)/d1
var VMA=0.0
VMA := na(VMA[1]) ? ta.sma(src, length) : sc*vi*src + (1 - sc*vi)*nz(VMA[1])

sc2 = 1/length2
pdm2 = math.max((src - src[1]), 0)
mdm2 = math.max((src[1] - src), 0)
var pdmS2 = 0.0
var mdmS2 = 0.0
pdmS2 := ((1 - sc2)*nz(pdmS2[1]) + sc2*pdm2)
mdmS2 := ((1 - sc2)*nz(mdmS2[1]) + sc2*mdm2)
s2 = pdmS2 + mdmS2
pdi2 = pdmS2/s2
mdi2 = mdmS2/s2
var pdiS2 = 0.0
var mdiS2 = 0.0
pdiS2 := ((1 - sc2)*nz(pdiS2[1]) + sc2*pdi2)
mdiS2 := ((1 - sc2)*nz(mdiS2[1]) + sc2*mdi2)
d2 = math.abs(pdiS2 - mdiS2)
s12 = pdiS2 + mdiS2
var iS2 = 0.0
iS2 := ((1 - sc2)*nz(iS2[1]) + sc2*d2/s12)
hhv2 = ta.highest(iS2, length) 
llv2 = ta.lowest(iS2, length) 
d12 = hhv2 - llv2
vi2 = (iS2 - llv2)/d12
var VMA2=0.0
VMA2 := na(VMA2[1]) ? ta.sma(src, length2) : sc2*vi2*src + (1 - sc2*vi2)*nz(VMA2[1])

//WWMA
var WWMA=0.0
WWMA := (1/length)*src + (1-(1/length))*nz(WWMA[1])

var WWMA2=0.0
WWMA2 := (1/length2)*src + (1-(1/length2))*nz(WWMA2[1])

//Zero Lag EMA [KivancOzbilgic]
EMA1a = ta.ema(src,length)
EMA2a = ta.ema(EMA1a,length)
Diff = EMA1a - EMA2a
ZLEMA = EMA1a + Diff

EMA12 = ta.ema(src,length2)
EMA22 = ta.ema(EMA12,length2)
Diff2 = EMA12 - EMA22
ZLEMA2 = EMA12 + Diff2

// Trend Mapping and Plotting //
FastTrend = TrendSelectorInput == "ALMA" ? ALMA : TrendSelectorInput == "DEMA" ? DEMA : TrendSelectorInput == "DSMA" ? EDSMA : TrendSelectorInput == "EMA" ? EMA : TrendSelectorInput == "HMA" ? HMA : TrendSelectorInput == "JMA" ? JMA : TrendSelectorInput == "KAMA" ? KAMA : TrendSelectorInput == "Linear Regression (LSMA)" ? LinReg : TrendSelectorInput == "RMA" ? RMA : TrendSelectorInput == "SMA" ? SMA : TrendSelectorInput == "SMMA" ? SMMA : TrendSelectorInput == "Price Source" ? src : TrendSelectorInput == "TEMA" ? TEMA : TrendSelectorInput == "TMA" ? TMA : TrendSelectorInput == "VAMA" ? VAMA : TrendSelectorInput == "VIDYA" ? VIDYA : TrendSelectorInput == "VMA" ? VMA : TrendSelectorInput == "VWMA" ? VWMA : TrendSelectorInput == "WMA" ? WMA : TrendSelectorInput == "WWMA" ? WWMA : TrendSelectorInput == "ZLEMA" ? ZLEMA : SMA
SlowTrend = TrendSelectorInput2 == "ALMA" ? ALMA2 : TrendSelectorInput2 == "DEMA" ? DEMA2 : TrendSelectorInput2 == "DSMA" ? EDSMA2 : TrendSelectorInput2 == "EMA" ? EMA2 : TrendSelectorInput2 == "HMA" ? HMA2 : TrendSelectorInput2 == "JMA" ? JMA2 : TrendSelectorInput2 == "KAMA" ? KAMA2 : TrendSelectorInput2 == "Linear Regression (LSMA)" ? LinReg2 : TrendSelectorInput2 == "RMA" ? RMA2 : TrendSelectorInput2 == "SMA" ? SMA2 : TrendSelectorInput2 == "SMMA" ? SMMA2 : TrendSelectorInput2 == "Price Source" ? src : TrendSelectorInput2 == "TEMA" ? TEMA2 : TrendSelectorInput2 == "TMA" ? TMA2 : TrendSelectorInput2 == "VAMA" ? VAMA2 : TrendSelectorInput2 == "VIDYA" ? VIDYA2 : TrendSelectorInput2 == "VMA" ? VMA2 : TrendSelectorInput2 == "VWMA" ? VWMA2 : TrendSelectorInput2 == "WMA" ? WMA2 : TrendSelectorInput2 == "WWMA" ? WWMA2 : TrendSelectorInput2 == "ZLEMA" ? ZLEMA2 : SMA2
plot(FastTrend, color=color.green, linewidth=LineWidth)
plot(SlowTrend, color=color.red, linewidth=LineWidth)

//Short & Long Options
Long = input.bool(true, "Model Long Trades", group="Core Settings")
Short = input.bool(false, "Model Short Trades", group="Core Settings")

// Entry & Exit Functions //
if (InDateRange and Long==true and FastTrend>SlowTrend)
    strategy.entry("Long", strategy.long, alert_message="Long")

if (InDateRange and Long==true and FastTrend<SlowTrend)
    strategy.close("Long", alert_message="Close Long")

if (InDateRange and Short==true and FastTrend<SlowTrend)
    strategy.entry("Short", strategy.short, alert_message="Short")

if (InDateRange and Short==true and FastTrend>SlowTrend)
    strategy.close("Short", alert_message="Cover Short")  

if (not InDateRange)
    strategy.close_all(alert_message="End of Date Range")
    

Published by ChaoZhang on the FMZ strategy square · last modified 2023-09-21. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.

Build this with AgenKit

A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.

in Claude Code, Cursor, Codex & 4 more
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Multi-Trend-Crossover-Strategy.md
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. Get tests, backtest, risk controls and a paper-trading switch

Understand it first

Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.

Related specs

esc

Try , , or .

↑↓ move↵ open