Topics like health, travel, finance, home, living, education and careers | Media Search Home

The Double Donchian Channel Breakout strategy coded for TradingView

A Donchian Channel is a popular tool with trend-following strategies. But that highest high and lowest low band does have a disadvantage: it can take a long time before the opposite band is crossed and the exit signal generates. Let"s see how we can address that issue by doubling the Donchian Channels.

IN THIS ARTICLE:

  • Trend following with the Double Donchian Channel Breakout strategy for TradingView
  • Trading rules for the Double Donchian Channel Breakout strategy
  • Code the Double Donchian Channel Breakout trading strategy for TradingView
    • Step 1: Define strategy settings and input options
    • Step 2: Calculate trading strategy values
    • Step 3: Output the strategy"s data and visualise signals
    • Step 4: Code the long trading rules
    • Step 5: Program the short trading conditions
    • Step 6: Open a trading position with entry orders
    • Step 7: Close market positions with exit orders
  • Performance of the Double Donchian Channel Breakout strategy for TradingView
    • Ideas for improvement and new strategies
  • Full code: the Double Donchian Channel Breakout strategy for TradingView
# Trend following with the Double Donchian Channel Breakout strategy for TradingView

In Trend Following (2006), Michael Covel shares his research and insights into some of the world"s best traders. One thing those top performers have in common is their trading methodology. All are trend followers, a trading approach with a seemingly simple goal: capture the majority of an up or down move for profit (Covel, 2006).

What makes trend followers different is that they don"t speculate when and where trends begin. Instead they simply monitor price. They know in advance what price moves define a trend, and only after a trend begins do they open positions (Covel, 2006). This does mean they always miss the start of a trend. And they neither get out near the top. But this can work fine: there"s plenty of money in the main move of big trends.

Most trend-following strategies share a few characteristics (Covel, 2006). They detect major trends by looking at price changes. Profitable positions are kept open until the trend ends. That makes profits run. Losing trades are closed at a predefined stop-loss level. That cuts losses short. And with position sizing the amount that each position loses is kept in balance.

One trend-following strategy is the Double Donchian Channel Breakout. This strategy is an attempt to improve the Donchian Channel Breakout strategy. That script kept losing positions open for a long time while we waited for price to cross the opposite Donchian Channel band. That not only made losses worse, it also reduced open profits considerably before the exit signal happened.

To fix that problem the Double Donchian Channel Breakout uses not one but two Donchian Channels (Covel, 2006). One has a long lookback period (and therefore a wider range), which we use for entries. The other band uses a short lookback period (and thus captures a smaller range of price action). That band is then used for exits. Let"s see what the strategy"s trading rules are.

# Trading rules for the Double Donchian Channel Breakout strategy

While Covel (2006) discusses several trend-following strategies, he only makes a short mention of the Double Donchian Channel Breakout strategy. So to come up with the trading rules below I combined the Donchian Channel Breakout strategy with some common sense and risk management principles from Covel"s (2006) book.

That gives the following trading rules:

  • Enter long:
    • Go long with a stop order when prices cross the upper Donchian Channel band of 100 bars.
  • Exit long:
    • Close any long positions when prices drop below the lower Donchian Channel band of 40 bars.
  • Enter short:
    • Go short with a stop order when prices cross the lower Donchian Channel band of 100 bars.
  • Exit short:
    • Close short positions when prices rise above the upper Donchian Channel band of 40 bars.
  • Position sizing:
    • The initial risk of each position (difference between entry price and 40-bar Donchian Channel) is 2% of equity.
    • The maximum exposure (that is, the margin to equity ratio) for a single position is 10% of equity.

The risk of positions we trade with this strategy is based on the 40-bar highest high and lowest low. When market volatility is low, that measure of risk is small. A small estimated risk can lead to a big calculated position size. And that becomes a problem when prices gap against our position, leading to losses much greater than intended.

To prevent the strategy from trading positions that are too big, we limit the exposure of each position to 10% of equity. That way not more than one tenth of the strategy"s equity is used for margin requirements.

The other strategies that Covel (2006) shares all use daily data from various US futures, including currencies (British Pound, Japanese Yen, Euro), commodities (crude oil, gold, silver, corn, wheat), soft commodities (coffee, sugar), and financials (S&P 500, Nasdaq 100, T-Note 5yr). So to test the Double Donchian Channel Breakout strategy we"ll also use daily futures data.

# Code the Double Donchian Channel Breakout trading strategy for TradingView

Now let"s turn the strategy"s rules into a proper TradingView strategy. An efficient way to do so is with a template. That adds structure and provides a framework for the different steps to code. Plus it breaks the programming task up into smaller, easier-to-manage portions.

This is the template we"ll use for the Double Donchian Channel Breakout strategy:

//@version=3 // Step 1) Define strategy settings // Step 2) Calculate strategy values // Step 3) Output strategy data // Step 4) Determine long trading conditions // Step 5) Code short trading conditions // Step 6) Submit entry orders // Step 7) Submit exit orders

If you want to follow along with the code discussion below, make a new strategy script in TradingView"s Pine Editor. Then paste in the above template. (If you just want the finished code, see the end of this article for the complete strategy.)

For an idea of what the code we"re going to write actually does, here"s how the finished Double Donchian Channel Breakout strategy looks on the chart:

Example chart of the Double Donchian Channel Breakout strategy for TradingViewExample chart of the Double Donchian Channel Breakout strategy for TradingView

Now let"s start and code a TradingView strategy based on two Donchian Channels.

# Step 1: Define strategy settings and input options

In the first step we define the strategy settings and its input options. For the settings we call the strategy() function:

// Step 1) Define strategy settings strategy(title="Double Donchian Channel Breakout", overlay=true, pyramiding=0, initial_capital=100000, commission_type=strategy.commission.cash_per_order, commission_value=4, slippage=2)

Here we use the title argument to name the script. With overlay set to true we have the strategy overlay on the chart"s instrument (and not appear in a subpanel).

We disable pyramiding (pyramiding=0) based on the strategy"s rules. With initial_capital we give the script a starting capital of 100,000 in the currency of the chart"s instrument.

For the costs we use 4 currency (commission_value=4) per single order (commission_type=strategy.commission.cash_per_order). These costs are a bit high, but it"s safer to overestimate than underestimate trading costs. For market and stop orders we use 2 ticks slippage (slippage=2).

# Inputs for the Donchian Channels length

Next we make several input options to easily configure the strategy"s parameters. The first input sets the Donchian Channel lengths:

// Donchian Channel inputs fastLen = input(title="Short Donchian Channel Length", type=integer, defval=40) slowLen = input(title="Long Donchian Channel Length", type=integer, defval=100)

These two inputs are integer input options (type=integer). We name the first ‘Short Donchian Channel Length’ and give it a starting value of 40 (defval=40). The other, ‘Long Donchian Channel Length’, begins with a value of 100.

We store these inputs in the fastLen and slowLen variables. That way we can easily reference the input"s current value by using the variable.

# Inputs for position sizing

Then we make inputs for the strategy"s position sizing:

// Position sizing inputs usePosSize = input(title="Use Position Sizing?", type=bool, defval=true) maxRisk = input(title="Max Position Risk %", type=float, defval=2, step=.25, minval=0.25, maxval=15) * 0.01 maxExposure = input(title="Max Position Exposure %", type=float, defval=10, step=1, minval=1, maxval=100) * 0.01 marginPerc = input(title="Margin %", type=integer, defval=10, minval=1, maxval=100) * 0.01

The first option we make here is a true/false input option (type=bool) named ‘Use Position Sizing?". We enable this checkbox by default (defval=true) and store its current value in the usePosSize variable. With this variable we have the strategy later use a default order size of 1 or the computed position size.

The next two inputs are floating-point inputs (type=float). The first, ‘Max Position Risk %", has a default of 2. We use this setting to define how much equity to risk per trade. The other is named ‘Max Position Exposure %". This one defines how much strategy equity we invest into a position"s margin requirements. Note that we multiply both inputs with 0.01 to express these percentage-based settings into a decimal value.

The last input is named ‘Margin %". This integer setting estimates the margin rate for the chart"s instrument. Unfortunately we can"t access that data in TradingView Pine at this time. So we have to guess what the instrument"s margin rate is. For a typical futures contract that rate varies between 5 to 15% of the total contract value (Kowalski, 2018). And so we use a default value of 10 here.

# Step 2: Calculate trading strategy values

Next we calculate the strategy"s data. There are three things we need to figure out: the Donchian Channel values, the position size, and the strategy"s trade window.

# Calculate Donchian Channels values

First we program the Donchian Channels:

// Step 2) Calculate strategy values // Calculate the Donchian Channel values ubSlow = highest(high, slowLen)[1] lbSlow = lowest(low, slowLen)[1] ubFast = highest(high, fastLen)[1] lbFast = lowest(low, fastLen)[1]

We first compute the 100-bar highest high of the slow Donchian Channel. For that we call the highest() function, which we execute on high prices (high) for slowLen bars (the input variable we set to 100 earlier). We put that 100-bar highest high in the ubSlow variable.

Then we calculate the 100-bar lowest low. We do that with TradingView"s lowest() function, which uses low prices (low) and a length of slowLen here. We store the lower band of the slow Donchian Channel in the lbSlow variable.

Next we calculate the fast Donchian Channel. We run the highest() function on high data for fastLen bars, the input variable we set to 40 earlier. To get the fast lower band we have lowest() calculate the 40-bar lowest low. We store these values in the ubFast and lbFast variables.

Note that we place the history referencing operator ([]) with a value of 1 behind each highest() and lowest() function call. This calculates the highest high and lowest low from the previous bars, without including the current bar"s data. (See calculate the highest high and lowest low for more details.)

# Calculate strategy"s position size

Then we figure out the strategy"s position size. For that we first calculate the percentage of equity we want to risk and the estimated trade risk:

// Calculate position size riskEquity = maxRisk * strategy.equity riskLong = (close - lbFast) * syminfo.pointvalue riskShort = (ubFast - close) * syminfo.pointvalue

To calculate the risk equity we multiply the maxRisk input variable with strategy.equity, a variable that returns the sum of the strategy"s initial capital, close trade profit, and open position profit (TradingView, n.d.). Since maxRisk has a default of 2%, multiplying it with strategy.equity tells us we can risk for that two percent.

For the trade risk estimation we make two calculations. The risk of a long trade is the price difference between the current price (close) and the 40-bar lowest low (lbFast). A short trade, on the other hand, has a price risk of the 40-bar highest high (ubFast) minus the current price.

We multiply both price differences with syminfo.pointvalue. That variable returns how much one full point of price movement is worth in currency terms. (For the E-mini S&P 500 future it returns 50, for instance.) This translate the price difference into a cash amount. We store those values in the riskLong and riskShort variables.

# Determine maximum position size

Next we figure out the maximum position size we"re allowed to trade:

maxPos = floor((maxExposure * strategy.equity) / (marginPerc * (close * syminfo.pointvalue)))

First we multiply the maxExposure input variable with strategy.equity. That tells us how many percent of the strategy"s equity we can invest in a position"s margin requirements. If the strategy"s equity is $100,000 and the ‘Max Position Exposure %’ input option set to 10, then we can"t invest more than $10,000 in margin.

We divide that value with the marginPerc input variable times the current price (close) times syminfo.pointvalue. That input variable returns our estimation of the margin rate for the chart"s instrument. When we combined with the instrument"s total contract value (close * syminfo.pointvalue) we know how much margin we need to reverse for 1 contract.

So to get the maximum allowed position size we divide how much we want to invest in margin with the margin requirement of one contract. We do that division inside the floor() function to round the outcome down to the nearest integer.

# Determine long and short order sizes

Then we use the values we just figured out to determine the actual order sizes:

longPosSize = usePosSize ? min(floor(riskEquity / riskLong), maxPos) : 1 shortPosSize = usePosSize ? min(floor(riskEquity / riskShort), maxPos) : 1

To give the longPosSize variable its value we first have TradingView"s conditional operator (?:) evaluate the usePosSize input variable. That variable returns true when the ‘Use Position Sizing?’ input option is enabled (and gives false when that checkbox is turned off).

When true, we calculate the long order size as follows. First we divide the riskEquity variable with riskLong. That tells us how many long contracts we can trade for our preferred maximum risk amount. We use the floor() function to round the outcome down to the nearest integer. This way we never trade a position that"s a bit too big.

Then we have the min() function return the smallest of two values: either the calculated long order size or the maxPos variable value. With this we never trade a position that"s bigger than the maximum allowed position size.

Should the usePosSize input variable be false, then the ‘Use Position Sizing?’ input option is disabled, and we have the conditional operator simply return 1. That way we always trade one contract when position sizing is turned off.

The way we set the value of the shortPosSize variable is very similar, except here we use the riskShort variable as a proxy for the short trade"s risk.

# Figure out trade window to flatten strategy

The last thing we need to compute in this step is the strategy"s trade window:

// Determine trade window tradeAllowed = (time <= timenow - (86400000 * 5)) and (n > slowLen)

The purpose of the strategy"s trade window is to make the script go flat when the backtest ends. That way there are no open trades in the performance report and values in the ‘Strategy Tester’ window don"t fluctuate when the market is open. But how does the strategy know that the backtest is about to end?

For that we define the tradeAllowed variable. The value of that variable is based on two logical expressions joined with the and operator. The first checks if the bar"s opening time (time) is less than or equal to (<=) the timenow variable minus 86,400,000 times 5. That 86.4 million value is the number of milliseconds in a day, and both time and timenow are also based on milliseconds.

So when we subtract 5 times the number of milliseconds in day from now, and then require that the price bar is before that point in time, we in effect make the strategy only trade till 5 days before the current date and time. Those five days give the strategy enough time to close trades and account for days the market is closed.

The other expression that sets the value of the tradeAllowed variable is n > slowLen. TradingView"s n variable returns the current bar number (TradingView, n.d.), and here we want that bar number to be bigger than the ‘Long Donchian Channel Length’ input option. This makes the strategy begin trading only after there"s enough price data to calculate both Donchian Channels (so 100 price bars at most).

# Step 3: Output the strategy"s data and visualise signals

For the third step we output the strategy"s data on the chart. That way we can track its behaviour and verify trade setups.

# Plot entry Donchian Channel

First we plot the Donchian Channel we use to enter trades:

// Step 3) Output strategy data // Plot Donchian Channel for entries plot(series=ubSlow, color=green, linewidth=2, title="Slow DoCh - Upperband") plot(series=lbSlow, color=red, linewidth=2, title="Slow DoCh - Lowerband")

We display the Donchian Channel"s bands with TradingView"s plot() function. The first plot() function call shows the 100-bar highest high (ubSlow). plot() makes a regular line plot by default, and here we make that line green. With the linewidth argument set to 2 the line is a bit bigger than normal.

The second plot() statement shows the 100-bar lowest low (lbSlow). We make that Donchian Channel band appear in the red colour with a line thicker than normal (linewidth=2).

# Plot exits Donchian Channel

Then we display the Donchian Channel used for exits:

// Plot Donchian Channel for exits plot(series=strategy.position_size < 0 ? ubFast : na, color=teal, style=linebr, linewidth=2, title="Fast DoCh - Upperband") plot(series=strategy.position_size > 0 ? lbFast : na, color=orange, style=linebr, linewidth=2, title="Fast DoCh - Lowerband")

To not clutter the chart with several lines, we only show part of the short-term Donchian Channel when there"s an open position. So when the script is long we plot the 40-bar lowest low. And when the strategy has an open short position we display the 40-bar highest high.

For that conditional plotting to work we set the series argument of the above plot() statements with TradingView"s conditional operator (?:). For the first plot() call that operator evaluates if the strategy.position_size variable is less than (<) 0, which happens when the strategy is short (TradingView, n.d.).

In that case the conditional operator returns the ubFast variable, and series then shows that 40-bar highest high on the chart. We show those values with a teal coloured line with breaks plot. When the script is flat or long, the conditional operator returns na to disable the plot.

The second plot() statement shows the 40-bar lowest low (lbFast) values when the strategy.position_size variable is greater than (>) 0. That happens when the strategy is long. In that case those low values show as an orange line with breaks. When the strategy is not long, we use na to disable the plotted line on those bars.

# Step 4: Code the long trading rules

Next we turn the strategy"s long trading rules into TradingView code. Since the strategy has us enter trades with a stop order, there"s are no enter long and enter short conditions. Instead we simply send stop orders when the strategy is flat to open a trade.

The strategy"s exit long rule is something we need to code, however. That rule closes longs when prices drop below the lower band of the 40-bar Donchian Channel. Here"s how we code that:

// Step 4) Determine long trading conditions exitLong = crossunder(close, lbFast) and (strategy.position_size > 0)

The exitLong variable we make here gets its true/false value from two expressions joined with the and operator. For the first we use the crossunder() function, which with the close and lbFast arguments returns true when the closing price dropped below the 40-bar lowest low (and else returns false).

The second requirement before we exit a long position is that strategy.position_size is greater than 0. With this check the strategy will only send an exit long order when there"s an open long position. If we"d sell when the strategy is flat or short, we"d only get a (bigger) short position.

# Step 5: Program the short trading conditions

The Double Donchian Channel Breakout strategy closes short positions when prices rise above the 40-bar Donchian Channel. We code that as follows:

// Step 5) Code short trading conditions exitShort = crossover(close, ubFast) and (strategy.position_size < 0)

The value of the enterShort variable depends on two expressions joined with the and operator. The first is the crossover() function with the close and ubFast variables as arguments. That returns true when the closing price crossed over the 40-bar highest high (and false otherwise).

The other requirement is that the script is short to begin with (strategy.position_size < 0). This way we don"t buy to cover a short position when the strategy is actually flat or already long.

# Step 6: Open a trading position with entry orders

For the sixth step we write the strategy code that opens positions. Here"s how we submit the script"s entry stop orders:

// Step 6) Submit entry orders if (strategy.position_size == 0) and tradeAllowed strategy.entry(id="EL", long=true, qty=longPosSize, stop=ubSlow + syminfo.mintick, oca_type=strategy.oca.cancel, oca_name="EntryOrders") strategy.entry(id="ES", long=false, qty=shortPosSize, stop=lbSlow - syminfo.mintick, oca_type=strategy.oca.cancel, oca_name="EntryOrders")

Since the Double Donchian Channel Breakout strategy opens trades with stop orders, we send both an enter long order and enter short order whenever the strategy is flat. We"ll use a OCA (One-Cancels-All) order group so that once an order fills, TradingView automatically cancels the other pending stop order.

To make that happen the above if statement first checks if the strategy is flat. That happens when the strategy.position_size variable equals (==) 0. We also want the current bar to be inside the strategy"s backtest window. That occurs when the tradeAllowed variable is true.

When those two things happen, the two strategy.entry() statements indented below if execute. The first strategy.entry() function opens a long trade (long=true) named ‘EL’ (id="EL"). We submit that order for longPosSize contracts, the variable that we earlier set to the computed position size (or give a value of 1 when position sizing is off).

We send that enter long order for the ubSlow + syminfo.mintick stop price. This places the stop at the 100-bar highest high (ubSlow) plus a single tick, which we get with TradingView"s syminfo.mintick variable. And so the smallest price fluctuation above the 100-bar Donchian Channel gets us into a long position.

The second strategy.entry() function call is much like the first. This time the function sends an enter short order (long=false) for shortPosSize contracts. We name that order ‘ES’. For the stop price we use the 100-bar lowest low (lbSlow) minus one tick (syminfo.mintick). This way the tiniest price move under the 100-bar Donchian Channel opens a short trade.

To not have both stop orders compute after one fills, we use a OCA order group (oca_type=strategy.oca.cancel) for both. Since both strategy.entry() orders use the same OCA group name (oca_name="EntryOrders"), TradingView knows they belong together. So when one fills the other gets cancelled.

# Step 7: Close market positions with exit orders

In this last step we close trades. There are two ways the strategy closes positions. The first is when the exit long or short signal happens. The other is when the backtest ends, when we flatten the strategy.

# Submit Donchian Channel exit orders

So first we submit the strategy"s exit long and short trades:

// Step 7) Submit exit orders if (exitLong) strategy.order(id="XL", long=false, qty=strategy.position_size) if (exitShort) strategy.order(id="XS", long=true, qty=abs(strategy.position_size))

The first if statement checks exitLong. Earlier we set that variable to true when the closing price dropped under the 40-bar lowest low while the strategy is long. When that happens this if statement executes strategy.order(). That function sends an order named ‘XL’ (id="XL") to close a long trade (long=false). To make the strategy flat we use an order quantity that"s the entire long position, which we fetch with TradingView"s strategy.position_size variable.

The second if statement looks up exitShort. That variable holds true when prices broke above the 40-bar highest high while the strategy is short. In that case the strategy.order() function sends the ‘XS’ order to cover a short trade (long=true). To have this order close the entire short position we submit it for strategy.position_size contracts. Since that variable returns a negative value when the strategy is short, we wrap it inside the abs() function. That way we get the absolute, positive value.

# Flatten strategy when backtest ends

The last line of the strategy exits trades when the backtest ends:

strategy.close_all(when=not tradeAllowed)

The strategy.close_all() function closes any open order with a market order when its when argument is true (TradingView, n.d.). Here that function makes the strategy go flat when not tradeAllowed is true.

Earlier we set the tradeAllowed variable to true when the script calculated on a price bar that happened after the first 100 bars but before 5 days from the current date and time. Outside that window the variable is false. But now at the end of the backtest we want a true value so that strategy.close_all() kicks into effect.

To make that happen we place the not logical operator before tradeAllowed. This returns true when tradeAllowed is false, and gives false when tradeAllowed is true.

Note that, since we also check the value of tradeAllowed before we open a trade, the strategy completely stops trading when that variable is false. This way the script only trades (and backtests) the time window we defined earlier.

# Performance of the Double Donchian Channel Breakout strategy for TradingView

Let"s begin our look at the strategy"s performance with something that the Double Donchian Channel Breakout strategy does well. True to its nature as a trend-following strategy, the script performs very well when prices experience a long trend.

An example of that is the following E-mini S&P 500 future chart. Here the strategy when long around 2,200 and closed the profitable long trade a whopping 400 points later:

Example of good performance of the Double Donchian Channel Breakout strategy for TradingViewExample of good performance of the Double Donchian Channel Breakout strategy for TradingView

Of course, the Double Donchian Channel Breakout strategy also has its weaknesses. The strategy suffers when prices move sideways. That environment gives losses because trends don"t start, prices move in the ‘wrong’ direction, and trends don"t continue long enough for a profitable exit.

An example of that underperformance is the chart below. Here the Double Donchian Channel Breakout had several losing trades in a row because E-mini S&P 500 future prices fluctuated up and down over the course of several months:

Underperformance of TradingViewUnderperformance of TradingView

The backtest performance of the Double Donchian Channel Breakout strategy shows below. The results are positive for both the E-mini S&P 500 future and EuroStoxx 50 future. Plus the win percentage is decent for a basic trend-following strategy.

Problematic is, however, the low number of trades. With around 2 trades per year there"s not enough data to say with confidence that the strategy does (or doesn"t) work. The results in the table below are even without position sizing so that the strategy could trade every signal it got. But that didn"t gave many trades, so further testing is still needed.

Performance metricE-mini S&P 500 future (ES)EuroStoxx 50 future (FESX)
First trade1998-02-031999-01-04
Last trade2018-11-042018-11-01
Time frame1 day1 day
Net profit$2,716€€38,172
Gross profit$97,840€€62,248
Gross loss-$95,124-€€24,076
Max drawdown$25,755€€9,944
Profit factor1.0292.585
Total trades4836
Win percentage41.67%52.78%
Avg trade$56.58€€1,060
Avg win trade$4,892€€3,276
Avg losing trade-$3,397-€€1,416
Win/loss ratio1.442.313
Commission paid$384€€288
Slippage2 ticks2 ticks
# Ideas for improvement and new strategies

While the backtest results are not horrible, we can probable make Double Donchian Channel Breakout strategy better. Here are some ideas that you might find valuable to explore further:

  • Like most trend-following strategies, the Double Donchian Channel Breakout strategy underperforms when markets move sideways. If we can filter out those unfavourable market conditions the strategy"s performance becomes a whole lot better. Perhaps an ADX or Average True Range (ATR) filter helps. We can also use moving averages, like the Donchian Trend strategy also does.
  • The parameter settings for the Double Donchian Channel Breakout strategy are chosen based on strategies shared by Covel (2006). Odds are they"re not the most optimal and that the strategy can perform better with other parameters values.
  • The strategy enters trades when prices move one tick above the 100-bar highest high and lowest low. This has us open positions as soon as possible. But not every peek outside a Donchian Channel is a valid breakout. Perhaps the strategy"s performance improves when we require that a bar closes a certain amount of ticks beyond the Donchian Channel.
  • The Double Donchian Channel Breakout strategy has no explicit stop, though the script does close trades when prices move against us. But the strategy might be easier to trade once we know there"s a stop in the market protecting against big losses. And with a time stop we can weed out those setups that go nowhere.
  • More ways to improve the strategy include risk management. We could, for instance, stop trading based on a losing day streak. Or limit the strategy"s maximum position size. See the risk management category for more ideas and inspiration.

See the Donchian Channel Breakout strategy for another take on the popular Donchian Channel indicator.

Other TradingView strategies that also trade high and low breakouts include the Donchian Trend strategy and the Donchian Trend with Time Exit strategy.

# Full code: the Double Donchian Channel Breakout strategy for TradingView

The complete code of the Double Donchian Channel Breakout strategy shows below. For more information and explanations refer to the discussion above.

//@version=3 // Step 1) Define strategy settings strategy(title="Double Donchian Channel Breakout", overlay=true, pyramiding=0, initial_capital=100000, commission_type=strategy.commission.cash_per_order, commission_value=4, slippage=2) // Donchian Channel inputs fastLen = input(title="Short Donchian Channel Length", type=integer, defval=40) slowLen = input(title="Long Donchian Channel Length", type=integer, defval=100) // Position sizing inputs usePosSize = input(title="Use Position Sizing?", type=bool, defval=true) maxRisk = input(title="Max Position Risk %", type=float, defval=2, step=.25, minval=0.25, maxval=15) * 0.01 maxExposure = input(title="Max Position Exposure %", type=float, defval=10, step=1, minval=1, maxval=100) * 0.01 marginPerc = input(title="Margin %", type=integer, defval=10, minval=1, maxval=100) * 0.01 // Step 2) Calculate strategy values // Calculate the Donchian Channel values ubSlow = highest(high, slowLen)[1] lbSlow = lowest(low, slowLen)[1] ubFast = highest(high, fastLen)[1] lbFast = lowest(low, fastLen)[1] // Calculate position size riskEquity = maxRisk * strategy.equity riskLong = (close - lbFast) * syminfo.pointvalue riskShort = (ubFast - close) * syminfo.pointvalue maxPos = floor((maxExposure * strategy.equity) / (marginPerc * (close * syminfo.pointvalue))) longPosSize = usePosSize ? min(floor(riskEquity / riskLong), maxPos) : 1 shortPosSize = usePosSize ? min(floor(riskEquity / riskShort), maxPos) : 1 // Determine trade window tradeAllowed = (time <= timenow - (86400000 * 5)) and (n > slowLen) // Step 3) Output strategy data // Plot Donchian Channel for entries plot(series=ubSlow, color=green, linewidth=2, title="Slow DoCh - Upperband") plot(series=lbSlow, color=red, linewidth=2, title="Slow DoCh - Lowerband") // Plot Donchian Channel for exits plot(series=strategy.position_size < 0 ? ubFast : na, color=teal, style=linebr, linewidth=2, title="Fast DoCh - Upperband") plot(series=strategy.position_size > 0 ? lbFast : na, color=orange, style=linebr, linewidth=2, title="Fast DoCh - Lowerband") // Step 4) Determine long trading conditions exitLong = crossunder(close, lbFast) and (strategy.position_size > 0) // Step 5) Code short trading conditions exitShort = crossover(close, ubFast) and (strategy.position_size < 0) // Step 6) Submit entry orders if (strategy.position_size == 0) and tradeAllowed strategy.entry(id="EL", long=true, qty=longPosSize, stop=ubSlow + syminfo.mintick, oca_type=strategy.oca.cancel, oca_name="EntryOrders") strategy.entry(id="ES", long=false, qty=shortPosSize, stop=lbSlow - syminfo.mintick, oca_type=strategy.oca.cancel, oca_name="EntryOrders") // Step 7) Submit exit orders if (exitLong) strategy.order(id="XL", long=false, qty=strategy.position_size) if (exitShort) strategy.order(id="XS", long=true, qty=abs(strategy.position_size)) strategy.close_all(when=not tradeAllowed)

See all TradingView example strategies for more trading ideas and other scripts to experiment with. There are also several TradingView example indicators on Kodify to explore.

References

Covel, M.W. (2006). Trend Following: How Great Traders Make Millions in Up or Down Markets (2nd edition). Upper Saddle River, NJ: FT Press.

Kowalski, C. (2018, August 30). Learn About Futures Margin. Retrieved on October 11, 2018, from https://www.thebalance.com/all-about-futures-margin-on-futures-contracts-809390

TradingView (n.d.). Pine Script Language Reference Manual. Retrieved on November 6, 2018, from https://www.tradingview.com/study-script-reference/

Last updated on June 2, 2019 (published December 1, 2018).
# Related TradingView tutorials
  • The Unilateral Pairs Trading strategy programmed for TradingView Pine

    The Unilateral Pairs Trading strategy for TradingView trades one side of an instrument pair. This way we long or short QQQ based on its ratio with SPY.

  • The Triple Moving Average strategy coded as a TradingView Pine Script

    The Triple Moving Average is a trend-following strategy. This TradingView script trades when two moving averages cross, with a third one as a filter.

  • The Simple Moving Average (SMA) Crossover strategy for TradingView

    The SMA Crossover strategy uses two moving averages to go long and short. With position sizing this TradingView trend-following strategy limits risks.

  • Programming the Bollinger Breakout strategy for TradingView

    The Bollinger Breakout strategy trades long and short breakouts based on a volatility channel. This TradingView strategy is based on the Bollinger bands.

  • Program the SMA Crossover Pyramiding trading strategy in TradingView Pine

    The SMA Crossover Pyramiding strategy trades with two moving averages. This TradingView trend-following strategy also pyramids into winning positions.

« All TradingView example strategies articles


Email: contact@about.com.vn - Phone: 818.333.007 - Website: Media Search Home
Copyright © 2007 - Noos. All rights reserved