We can configure a TradingView strategy’s pyramiding settings by hand or with code. But our TradingView strategy will not always respect that setting. Why is that? And how do we prevent our script from opening positions that are too big?

In this article:

Pyramiding in TradingView and the effect of several entry orders

Configuring a strategy in advance – so that the script is always added to the chart with the right settings – is done with the strategy() function, and each TradingView strategy script has to use that function (Pine Script Language Tutorial, n.d.). We also need to set this function’s title argument always to specify the strategy’s name (TradingView, n.d.).

Another setting we can configure with strategy() is the strategy’s pyramiding option, which specifies how many orders may be executed in the same direction (TradingView, n.d.). We set that option with the pyramiding argument, and by default a strategy only enters one order in the same direction and then rejects any additional entry orders for the same direction (TradingView, n.d.).

However, even when we set a strategy’s pyramiding setting, there’s no guarantee that our script doesn’t open more orders in the same direction than we specified. So when we allow two entries in the same direction (pyramid=2), we can have positions with four or more entries.

There are two causes of that confusing behaviour, depending on which function we use to submit the entry order:

  • The strategy.order() function does not take the pyramiding setting into account (TradingView, n.d.). That means when we submit entry orders with this function, they’re executed regardless of the number of currently open entries. We examine this more closely in the strategy.order() function and a strategy’s pyramiding.
  • While the strategy.entry() function does respect the strategy’s pyramiding settings, we can still end up with a bigger position than we allowed with the pyramiding settings. This is due to the difference between the order generation state and order execution stage (see Pine Script Language Tutorial, n.d.). As a consequence, an order can satisfy all conditions (including the pyramiding limit) when it generates, but when it’s actually filled then its conditions may have been invalidated.

That latter cause that makes a script not follow the strategy’s pyramiding setting is what we discuss in this article. We’ll look at the order generation and order execution stages below. After that we’ll examine a strategy that shows a practical example of this behaviour, and then look at two solutions.

The difference between generating and executing orders

To understand why our strategy can open positions bigger than allowed by the pyramiding argument of the strategy() function, let’s look at the two order phases in TradingView (Pine Script Language Tutorial, n.d.):

  • In the order generation stage TradingView evaluates three order conditions. The first is the situation that triggers the order (like a moving average crossover), and this is something we evaluate with an if statement or with the when argument of the strategy.entry() function. The next condition is whether the number of open entries are less than the pyramid setting. And the last order condition are the strategy’s risk management settings (like the maximum number of orders per day). Only when all three conditions allow generating an order, we move on to the order execution phase (Pine Script Language Tutorial, n.d.).
  • The order execution stage is the moment when the order actually fills. Since this happens a short time after it generates, several conditions might have changed. For instance, our enter long or enter short logic can be invalidated. Furthermore, another entry order might be filled in the meantime. In that case, the currently open position may already be at its maximum number of entries before our latest order fills. This situation is what makes our strategy open larger positions than allowed by the pyramiding argument.
Tip: The strategy.order() function is less strict when submitting entry orders since it doesn’t take the strategy’s pyramid and risk management settings into account during the order generation stage (see Pine Script Language Tutorial, n.d.).

What these two distinct phases mean is that an order can satisfy all order conditions (like the pyramid setting) when it generates. But when the time comes for the order to actually fill, those conditions can be invalid. However, at that point the order is already on its way and cannot be cancelled by TradingView anymore.

For example, when we don’t allow pyramiding (that is, pyramiding=0) and submit two market orders at the same time, then both orders get filled since they’re market orders and execute immediately at the current price. But the second order doesn’t get cancelled. Instead, both orders fill at the same moment and TradingView doesn’t have time to process the first order fill and then cancel the second one before it gets executed (Pine Script Language Tutorial, n.d.). We see the same behaviour happening with limit orders with similar or nearly the same prices.

A TradingView strategy therefore places all orders that don’t contradict the rules at the moment they were generated. Of course, if we already have an open position and don’t allow pyramiding, then any additional order generated by strategy.entry() is cancelled during the order generation stage and that newly generated order won’t be executed.

Tip: The matter in which the time lag between order generation and order execution affects your script depends on the orders you use (market orders fill faster than limit orders) and how quickly after each other the strategy can submit orders. Generally speaking, the more orders you submit in a short period of time, the greater the odds that the script ends up with a bigger position than intended. This is particularly likely when a strategy calculates on every tick or when we use strategy.entry() more than once in the script to submit several kind of entry orders (we’ll see an example of that below). On the other hand, if we submit at most one market order on bar close, then there is (depending on how long it takes before a bar closes) more than enough time between consecutive orders for TradingView to respect the pyramiding setting.

Let’s see how the above theoretical explanation works in practice with a programming example that shows an exhibit of this behaviour. After that we’ll discuss two solutions that prevent TradingView from opening a position that’s larger than specified by the pyramiding argument of the strategy() function.

Example strategy: pyramiding and submitting several orders at the same time

In the example strategy below we submit up to three enter long orders at the same time while we only allow one entry in the same direction. Our conditions for these enter long orders are when the bar’s high is the highest of the recent 5 bars, a volume reading that’s above its 5-bar average, or a 2-period EMA (Exponential Moving Average) that crossed above the 15-bar EMA.

Since those long conditions are not mutually exclusive, our script can generate several long orders on the same bar. We do that deliberately, since then we can see how a strategy can open a position bigger than allowed by its pyramiding setting. The chart below gives a quick view of the strategy’s behaviour (the highlighted trade shows how the pyramiding setting isn’t respected); after discussing the code we’ll explore the strategy’s behaviour and workarounds in depth.

Example of our TradingView strategy that doesn't respect the pyramiding settings
//@version=2
strategy(title="Pyramiding and several entry orders", pyramiding=0, 
     overlay=true)

// Determine trading conditions
fiveBarHigh     = (high == highest(high, 5))
volumeCrossover = crossover(volume, sma(volume, 5))
maCrossover     = crossover(ema(close, 2), ema(close, 15))

// Submit orders
if (fiveBarHigh)
    strategy.entry(id="Long Entry #1", long=true) 
    
if (volumeCrossover)
    strategy.entry(id="Long Entry #2", long=true, stop=high)
    
if (maCrossover)
    strategy.entry(id="Long Entry #3", long=true, 
         stop=high + 10 * syminfo.mintick)
    
if (dayofweek == 6)
    strategy.close_all()

We start with the @version=2 comment. This way we use the second version of Pine Script, and with that version we can use if statements in our code (Pine Script Language Tutorial, n.d.).

Then we configure the strategy’s settings with strategy(). We use this function’s title argument to name the strategy and, with pyramiding=0, disable the strategy’s pyramiding feature. That value of 0 only allows our strategy to open one entry in the same direction, and then TradingView will reject any additional entries for the same direction (TradingView, n.d.). We also set the overlay argument to true. That displays the strategy on the instrument instead of in a separate subchart.

Next we determine the trading conditions:

fiveBarHigh     = (high == highest(high, 5))
volumeCrossover = crossover(volume, sma(volume, 5))
maCrossover     = crossover(ema(close, 2), ema(close, 15))

Each of these three true/false variables is assigned its value based on a single expression. For the value of the fiveBarHigh variable we evaluate whether the high of the current bar (high) equals (==) the highest high of the recent five bars (including the current bar). We retrieve that value with highest() and two arguments: a series of values to get the highest value from and the number of bars to calculate on (TradingView, n.d.). Here we set those arguments to the bar’s high prices (high) and 5.

The next variable, volumeCrossover, is assigned the value returned by crossover(). That function returns true when its first argument has, on the current bar, a value that’s greater than the second argument while, on the previous bar, the first argument’s value was less than that of the second (TradingView, n.d.). Now when such a crossover didn’t happen, crossover() returns false.

The values we use with that function are the volume of the current bar (volume) and the 5-bar average volume. We calculate that latter with sma(), a function that returns the value of a Simple Moving Average based on two arguments: a series of values to process and the number of bars to calculate on (TradingView, n.d.). We use it with volume and 5 here to compute the 5-bar SMA of the instrument’s volume. With the combination of crossover() and sma() our volumeCrossover variable holds true when the current bar’s volume crossed above its 5-bar average and false in all other cases.

The third and last true/false variable, maCrossover, is also assigned the value crossover() returns. This time we have the function calculate with two ema() function calls. That latter function calculates an Exponential Moving Average with two arguments: a series of values to compute on and an integer that sets the moving average’s length in number of bars (TradingView, n.d.). Here we have them calculate on the bar’s closing prices (close) for a length of 2 and 15 bars. That means our crossover() function call returns true when the 2-bar EMA crossed above the 15-bar EMA, and returns false otherwise.

Then we submit up to three orders to open a long position:

if (fiveBarHigh)
    strategy.entry(id="Long Entry #1", long=true) 
    
if (volumeCrossover)
    strategy.entry(id="Long Entry #2", long=true, stop=high)
    
if (maCrossover)
    strategy.entry(id="Long Entry #3", long=true, 
         stop=high + 10 * syminfo.mintick)

We submit the orders conditionally with an if statement, and each if statement evaluates one of the variables we’ve just made. Now when that variable’s value is true on the current bar, then the indented code below the if statement executes (see Pine Script Language Tutorial, n.d.).

The strategy submits the orders with strategy.entry(). That function opens or adds to a position with a market order by default, and also respects the strategy’s pyramiding setting (TradingView, n.d.). We use this function with up to three arguments. With id we specify the order identifier, and that name displays on the chart and in the ‘Strategy Tester’ window. The long argument, when set to a value of true, makes strategy.entry() submit an enter long order while long=false has it send off an enter short order (TradingView, n.d.). And the stop argument allows us to submit a buy or sell short stop, and for that we need to set this argument to a specific price (TradingView, n.d.).

Our first if statement evaluates the fiveBarHigh variable and, when true, calls strategy.entry(). With that function we submit an enter long order (long=true) named “Long Entry #1”.

The next if statement checks the value of volumeCrossover. When that variable holds true, we call the strategy.entry() function again. This time we submit the “Long Entry #2” enter long (long=true) order with a stop at the current bar’s high (stop=high). This has TradingView submit a buy market order as soon as the bar’s high is touched.

The third and last if statement processes maCrossover. When that true/false variable is true, we again use strategy.entry() to submit the “Long Entry #3” enter long (long=true) order. Now this order is a buy stop 10 ticks above the current bar’s high. We get that stop price with the bar’s high (high) plus 10 times syminfo.mintick, a built-in variable that returns the minimum tick value (that is, the minimum price change) of the current symbol (TradingView, n.d.).

That way we standardise the 10 tick offset. That is, with syminfo.mintick it doesn’t matter whether the instrument quotes with five decimals (such as EUR/USD), two (like the S&P 500 Index), or none (the EuroStoxx 50 future): our strategy always submits a buy stop 10 ticks above the current bar’s high.

We end the programming example by closing our position:

if (dayofweek == 6)
    strategy.close_all()

This if statement checks whether dayofweek equals (==) 6. That dayofweek variable returns the current bar’s day of week in the exchange’s time zone (TradingView, n.d.), starting with 1 for Sunday to 7 for Saturday.

So by checking whether it returns 6, we’re evaluating whether the current day is Friday. When it is, we call strategy.close_all(). That function exits the current market position and makes the strategy flat, while it doesn’t do anything when there isn’t an open position (TradingView, n.d.). With this arbitrary exit, we ensure that our positions are closed after at most a few days and that the script can generate enough trades.

Example: a TradingView strategy that submits several entry orders

Now let’s examine the behaviour of our example strategy. We began the programming example with the strategy() function as follows:

strategy(title="Pyramiding and several entry orders", pyramiding=0, 
     overlay=true)

Now with the pyramiding argument set to 0, we’ve disabled the strategy’s pyramiding and our strategy should – at least in theory – only execute one order in the same direction.

Before verifying whether the strategy actually does that, let’s check if the pyramiding setting is indeed disabled. For that we click on the gear icon ( ) that’s displayed to the right of the strategy’s name on the chart:

Opening the strategy settings window in TradingView

This opens a window with the strategy settings. Here we go to the ‘Properties’ tab and there we can see the ‘Pyramiding’ option indeed disabled:

TradingView strategy settings confirm: pyramiding is disabled

Now let’s turn our attention to the strategy’s behaviour. When we inspect the charts, we see several bars on which the strategy executed more than one entry in the same direction despite our pyramiding setting:

Example of how the initial TradingView strategy doesn't respect the pyramiding setting Example of how the initial TradingView strategy doesn't respect the pyramiding setting Example of how the initial TradingView strategy doesn't respect the pyramiding setting

When we look at the code, we see an explanation for our strategy’s problem: we use strategy.entry() multiple times with conditions of which several can happen on the same bar. For example, when a moving average and volume crossover happen on the same bar, then our strategy doesn’t generate one order but two enter long orders.

More specifically, during that script calculation the strategy.entry() function is called twice. Both times the function generates an enter long order. But when there isn’t an open position yet when those two crossovers happen, then both orders are approved by TradingView in the order generation stage. This happens even when the pyramiding condition will be invalidated when the orders fill. In other words, our strategy does generate both orders but doesn’t think ahead to take into account that executing both orders violates the strategy’s pyramiding setting.

So when we call strategy.entry() multiple times, each strategy.entry() function call can generate an order that’s subsequently submitted by TradingView – even though the pyramiding argument of the strategy() function wouldn’t approve the order (Pine Script Language Tutorial, n.d.). But once an order leaves the order generation stage, it cannot be cancelled (Pine Script Language Tutorial, n.d.).

Luckily, we can make two adjustments to our code that prevents the strategy from opening a position that’s bigger than the pyramid setting allows:

  • With an OCA (one cancels all) order group other pending entry orders are cancelled as soon as one entry order is filled. In a sense, this approach ‘ties’ orders together so that they’re treated as a group in the order generation and execution phases.
  • Another way is to restructure the code so that entry conditions become mutually exclusive.

Let’s explore how we can implement both solutions and how that affects the strategy’s behaviour.

Solution 1) Implementing an OCA group for entry orders

So when a strategy doesn’t respect its pyramiding setting, one solution is to place entry orders in an OCA (one cancels all) order group that uses the strategy.oca.cancel variable setting (Pine Script Language Tutorial, n.d.).

With one-cancels-all (OCA) orders we place multiple, and perhaps unrelated, orders in the same group with the goal of just having one order fill, and then having the other orders cancelled (Interactive Brokers, n.d.). So when one OCA order fills in TradingView, other orders from the same group are cancelled (Pine Script Language Tutorial, n.d.).

Note: The OCA approach is not 100% reliable: when order prices are identical or very close, then more than one order of the same group can fill before TradingView has a chance to cancel the other order(s) (Pine Script Language Tutorial, n.d.). When a script uses orders with practically the same prices, a better approach to prevent too many entries in the same direction is to make entry orders mutually exclusive (see example further down below).

Now let’s adjust the above programming example to one that uses OCA orders to prevent the strategy from executing more than one of its three entry orders:

//@version=2
strategy(title="Pyramiding and several entry orders", pyramiding=0, 
     overlay=true)

// Determine trading conditions
fiveBarHigh     = (high == highest(high, 5))
volumeCrossover = crossover(volume, sma(volume, 5))
maCrossover     = crossover(ema(close, 2), ema(close, 15))

// Submit orders
if (fiveBarHigh)
    strategy.entry(id="Long Entry #1", long=true, 
         oca_type=strategy.oca.cancel, oca_name="Long Entry")
    
if (volumeCrossover)
    strategy.entry(id="Long Entry #2", long=true, stop=high,
         oca_type=strategy.oca.cancel, oca_name="Long Entry")
    
if (maCrossover)
    strategy.entry(id="Long Entry #3", long=true, 
         stop=high + 10 * syminfo.mintick,
         oca_type=strategy.oca.cancel, oca_name="Long Entry")
    
if (dayofweek == 6)
    strategy.close_all()

This script version is nearly the same as the one we discussed above. The only difference is that, in order to implement the OCA order group, we added two arguments to the strategy.entry() function calls:

if (fiveBarHigh)
    strategy.entry(id="Long Entry #1", long=true, 
         oca_type=strategy.oca.cancel, oca_name="Long Entry")
    
if (volumeCrossover)
    strategy.entry(id="Long Entry #2", long=true, stop=high,
         oca_type=strategy.oca.cancel, oca_name="Long Entry")
    
if (maCrossover)
    strategy.entry(id="Long Entry #3", long=true, 
         stop=high + 10 * syminfo.mintick,
         oca_type=strategy.oca.cancel, oca_name="Long Entry")

The strategy.entry() statements already used the id, long, and stop arguments – and now we’ve added oca_type and oca_name.

The oca_type argument specifies the type of OCA group, and with strategy.oca.cancel the order group becomes the kind where, when one order fills, the other pending orders are cancelled (TradingView, n.d.). And we use the oca_name argument to name our order group (TradingView, n.d.). This makes it possible to have multiple order groups in the same script by using different names for them.

Each entry order of the “Long Entry” order group uses strategy.oca.cancel. And so when one long entry fills, TradingView attempts to cancel the other pending long orders. Let’s say two enter long orders are approved in the order generation stage and, in the order execution stage, the first order fill. TradingView then attempts to cancel the other order. This way it matters less that multiple orders are generated in the order execution stage, since with an OCA order group they can still be cancelled while being in the order execution stage.

However, TradingView will attempt and can cancel the other pending orders. But there’s no guarantee that this succeeds. When the pending orders are market orders or have prices close to each other, then TradingView has practically no time to cancel the other pending order(s) when the first order of the group fills.

In our programming example, that risk isn’t an issue since we use one market order and two stop orders with different prices. That way, when the market order fills and the stop prices haven’t been touched yet, TradingView has time to cancel those stop orders.

Example charts: multiple entries versus OCA orders

Now let’s see how our strategy behaves when it uses an OCA order group to manage multiple entries in the same direction. Without such an order group, the strategy sometimes fills more than one order per bar:

Example of how the initial TradingView strategy doesn't respect the pyramiding setting

Now when we use OCA orders, then the double entry in the chart above is replaced by a single entry:

Example chart when the strategy uses OCA orders in TradingView

This chart also shows that the “Long Entry #1” order executes but “Long Entry #2” doesn’t. This happens since the latter is a stop order and so when the market order (“Long Entry #1”) fills, TradingView has the opportunity to cancel the stop order (provided it’s not yet triggered). Should “Long Entry #2” also be a market order, we can’t expect TradingView to cancel it in time.

Looking at another chart period, the example strategy previously performed like this:

Example of how the initial TradingView strategy doesn't respect the pyramiding setting

Now with the OCA order group, the double and triple entries on the highlighted price bars are gone. Instead, the strategy only enters once per bar now:

Example chart of our TradingView strategy using OCA orders

Now let’s look at the third and last chart. Without an one-cancels-all order group, the strategy behaved like:

Example of how the initial TradingView strategy doesn't respect the pyramiding setting

With OCA, the strategy’s pyramiding setting is respected and entries are limited to once per bar:

Example chart of the TradingView strategy submitting OCA orders

Now let’s examine another approach that we can use to prevent TradingView from filling more than one order in the same direction.

Solution 2) Create mutually-exclusive entry conditions

As opposed to OCA orders, mutually-exclusive entry conditions do guarantee that we don’t end up with a position bigger than intended. After all, when entry conditions can’t happen at the same time, our script cannot submit more than one entry order simultaneously. That gives enough time between successive entry signals for TradingView to respect the strategy’s pyramiding setting. Another benefit is that we can then use market orders too, which fill too fast for TradingView to successfully cancel them in an OCA group.

So let’s change our original programming example to one that uses mutually-exclusive entry orders so that we don’t end up with more than one entry order filled in the same direction:

//@version=2
strategy(title="Pyramiding and several entry orders", pyramiding=0, 
     overlay=true)

// Determine trading conditions
fiveBarHigh     = (high == highest(high, 5))
volumeCrossover = crossover(volume, sma(volume, 5))
maCrossover     = crossover(ema(close, 2), ema(close, 15))

// Submit orders
if (fiveBarHigh and not volumeCrossover and not maCrossover)
    strategy.entry(id="Long Entry #1", long=true)
    
if (volumeCrossover and not fiveBarHigh and not maCrossover)
    strategy.entry(id="Long Entry #2", long=true, stop=high)
    
if (maCrossover and not fiveBarHigh and not volumeCrossover)
    strategy.entry(id="Long Entry #3", long=true, 
         stop=high + 10 * syminfo.mintick)
    
if (dayofweek == 6)
    strategy.close_all()

Most code is the same, so let’s only examine the difference with the original version that executed more than one order per bar. In the updated version, we change the condition of the if statements that submit orders. Besides the true/false variable with the entry logic, we now also require that the two variables with the other entry conditions are false:

if (fiveBarHigh and not volumeCrossover and not maCrossover)
    strategy.entry(id="Long Entry #1", long=true)
    
if (volumeCrossover and not fiveBarHigh and not maCrossover)
    strategy.entry(id="Long Entry #2", long=true, stop=high)
    
if (maCrossover and not fiveBarHigh and not volumeCrossover)
    strategy.entry(id="Long Entry #3", long=true, 
         stop=high + 10 * syminfo.mintick)

Each if statement now evaluates three true/false expressions: the variable with the original entry condition (like the 5-bar high or EMA crossover) besides the opposite of the two other entry conditions. By checking whether the two other entry conditions did not happen, we make the orders mutually exclusive: now the strategy.entry() function can only be called when only one of the three entry conditions is true.

To do that we combine the three true/false expressions in each if statement with the and logical operator. That operator returns true when the value on its left and the value on its right are both true too. And when one or both values are false, then the result combined by and is false too (Pine Script Language Tutorial, n.d.).

For instance, the first if statement still requires that the fiveBarHigh variable evaluates to true before the strategy submits the “Long Entry #1” order. So for this order order to be executed, the current bar’s high needs to be the highest high of the recent 5 bars. However, we now also require that the two other true/false variables (volumeCrossover and maCrossover) are false.

We check that latter with the not logical operator, which performs logical negation (Pine Script Language Tutorial, n.d.). This means when we place not for an expression that returns true, then not returns false. Likewise, not placed before something that’s false returns true.

So before the strategy can submit its first order, the volumeCrossover variable has to be false because we’re checking whether not volumeCrossover is true. Similarly, we require not maCrossover to be true too. This means we submit the “Long Entry #1” order when the current bar high is the 5-bar high, but the volume has not crossed above its 5-bar moving average and nor did the 2-bar EMA cross above the 15-bar EMA. When a volume or exponential moving average crossover did happen when a new 5-bar high happened, then the if statement’s condition is false and the strategy.entry() function isn’t called to submit the order.

Given that the two other if statements are structured in the same way, all of our three strategy.entry() function calls are mutually exclusive: the entry order is only submitted when one of the three entry conditions is true. When two or three entry conditions are true at the same time, then the order isn’t send off.

Example charts: multiple entries versus mutually-exclusive orders

Now let’s see how the strategy behaves with those mutually-exclusive orders. The original version could submit several entry orders on the same bar like this:

Example of how the initial TradingView strategy doesn't respect the pyramiding setting

The strategy performs on the same chart period like this when we use exclusive entry orders:

Example of how the TradingView strategy behaves when using exclusive entries

Likewise, the initial strategy version had no problem with filling two or even three entry orders on the same bar:

Example of how the initial TradingView strategy doesn't respect the pyramiding setting

But when we require that entry orders are only submitted when several entry conditions didn’t occur at the same time, we see the script entering once per bar:

Example chart of the TradingView strategy when using mutually-exclusive orders

And in our third chart example the original strategy version previously looked like:

Example of how the initial TradingView strategy doesn't respect the pyramiding setting

Now with mutually-exclusive orders we’ve drastically reduced the number of entries per bar:

Example chart of the TradingView strategy when it uses exclusive entry orders

Summary

Each TradingView strategy has to use strategy(). This function’s pyramiding argument specifies how many entries in the same direction the strategy may open. With its default value of 0, only one entry in the same direction is allowed. As soon as an order generates, TradingView checks the pyramiding setting before approving the order. But since there’s a time lag between generating an order and having it actually fill, several other entry orders may also have been approved in the meantime and are waiting to be filled too. When they execute, our strategy can have opened a position that’s bigger than allowed by pyramiding. In a sense, strategies don’t look ahead to see what happens after an order fills. There are two ways to prevent this behaviour. The first is to place entry orders in an OCA (one-cancels-all) order group. Then when one order fills, TradingView attempts to cancel the other pending orders. This requires that the orders have different prices to give TradingView a chance to actually cancel the pending orders before they execute. The second approach is to create mutually-exclusive order conditions. That way when an order generates, we know that the same script calculation didn’t generate another order too. We can also use this approach with market orders or orders that have prices that are too close to each other to have TradingView cancel them successfully in an OCA group.

Learn more:


References

Interactive Brokers (n.d.). One-Cancels-All (OCA) Orders. Retrieved on April 27, 2016, from https://www.interactivebrokers.com/en/index.php?f=617

Pine Script Language Tutorial (n.d.). Retrieved on February 24, 2016, from https://docs.google.com/document/d/1sCfC873xJEMV7MGzt1L70JTStTE9kcG2q-LDuWWkBeY/

TradingView (n.d.). Script Language Reference Manual. Retrieved on April 27, 2016, from https://www.tradingview.com/study-script-reference/