One strategy setting that we can configure in TradingView is the script’s initial capital. How do we set that starting equity, and how does it influence the strategy’s behaviour and performance?

In this article:

Setting the initial equity of a TradingView strategy programmatically

We configure a TradingView strategy by hand or with code, and with that latter the script is always added to the chart with the right settings. Setting a strategy’s properties with code is done with strategy(). That function needs to be in every strategy’s code (Pine Script Language Tutorial, n.d.) and its title argument, which specifies the strategy’s name, always needs to be set (TradingView, n.d.).

Another argument of strategy() is initial_capital. This argument sets the strategy’s initial capital (TradingView, n.d.), which is the capital used by the script when backtesting and forward testing on real-time data. Note that this initial capital is, however, not the same as the account balance (“Admin”, 2016). That latter value is used in the ‘Trading Panel’ window and shows the paper trading or live broker account balance. That balance is available for all strategies trading the account, whereas the initial capital is a strategy-specific setting.

When we don’t specify the initial_capital argument, it defaults to 100,000. To set the starting value of the strategy’s capital to something else (like 10k), we use the strategy() function as follows:

strategy(title="Example - initial_capital", initial_capital=10000)

A strategy’s initial capital influences several things. First, it affects the performance report in the ‘Strategy Tester’ window by setting the strategy’s capital. It also influences default order sizing based on an equity percentage. And the initial capital is also reflected in built-in TradingView variables like strategy.equity that returns the sum of initial capital, net profit, and open profit and strategy.initial_capital, which returns the strategy’s initial capital (TradingView, n.d.).

Tip: The currency argument of the strategy() function specifies the strategy’s currency, and that setting also influences the cash our strategy has available. For more on how currency conversion affects the strategy equity set with initial_capital, see initial capital, currency conversion, and a strategy’s equity.

Setting the starting capital of a TradingView strategy by hand

While we can specify strategy settings programmatically with strategy(), we can also override those settings by hand. That provides us with additional flexibility to configure multiple instances of the same strategy differently.

To manually change a strategy’s initial capital, 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 different strategy settings. Here we select the ‘Properties’ tab and there we specify the strategy’s starting funds with the ‘Initial Capital’ setting:

Configuring a strategy's initial capital by hand

Example: Bollinger Bands breakouts and initial capital set programmatically

Let’s see how a script can use initial_capital. The strategy below plots Bollinger Bands based on a 40-bar Simple Moving Average (SMA) with a standard deviation of the same length. The Bollinger Bands generate a trading signal whenever the price exceeds a band, based on the idea that we can expect the trend to continue after such a breakout (Pring, 2002).

To trade this upside and downside momentum, we go long whenever the closing price crosses above the upper Bollinger Band and initiate a short position each time the bar’s close drops below the lower band. We exit any open position when the bar crosses the price band that’s between the upper and lower Bollinger Bands.

The image below gives a brief look of how the script trades; after discussing the code, we’ll look at the strategy’s behaviour in depth and examine how initial_capital affects the script.

Example chart of the Bollinger Bands trading strategy in TradingView
strategy(title="Bollinger Bands breakout", overlay=true, 
     initial_capital=10000)

// Input options
bolLength = input(title="Bollinger Bands Length", type=integer, defval=40)
sdOffset  = input(title="StDev Offset", type=float, defval=2, 
     minval=0.1, step=0.25)

// Compute values
maPrice = sma(close, bolLength)
sdPrice = stdev(close, bolLength)

upperBand = maPrice + (sdOffset * sdPrice)
lowerBand = maPrice - (sdOffset * sdPrice)

orderSize = floor((0.50 * strategy.equity) / close)

// Plot Bollinger Bands
plot(series=upperBand, color=green, linewidth=2)
plot(series=maPrice, color=orange)
plot(series=lowerBand, color=red, linewidth=2)

// Enter and close long orders
strategy.entry(id="Enter Long", long=true, qty=orderSize, 
     when=crossover(close, upperBand))
     
strategy.close(id="Enter Long", when=crossunder(close, maPrice))

// Enter and close short orders
strategy.entry(id="Enter Short", long=false, qty=orderSize, 
     when=crossunder(close, lowerBand))
     
strategy.close(id="Enter Short", when=crossover(close, maPrice))

We first specify the strategy’s settings with strategy(). We use this function’s title argument to name the strategy and, with overlay set to true, plot the strategy on the chart’s instrument (TradingView, n.d.). With initial_capital=10000 our strategy begins the backtest with 10,000 equity.

Then we add several input options to the script:

bolLength = input(title="Bollinger Bands Length", type=integer, defval=40)
sdOffset  = input(title="StDev Offset", type=float, defval=2, 
     minval=0.1, step=0.25)

The input() function adds inputs to a script, and also returns the input’s current value (TradingView, n.d.). We store that returned value in a variable with the assignment operator (=). That way we can refer to the input’s value later on in the script by using its variable.

We make two inputs here, both numerical inputs. The first accepts whole numbers and is made by setting the type argument of the input() function to integer. The other input has that argument set to float, and that makes it accept decimal values too (Pine Script Language Tutorial, n.d.).

With the title argument we name the first input “Bollinger Bands Length” and we set its standard value (defval) to 40. The current value we track with the bolLength variable; we’ll use that variable later on as the length of the moving average and standard deviation.

The other input is called “StDev Offset” and has a default of 2. Its minimum value (minval) is 0.1 and with step=0.25 the input’s value changes with 0.25 each time we click on the numerical input’s up/down arrows. We store its value in sdOffset, and use that variable later when adding or subtracting a standard deviation multiple from the SMA.

Next we calculate the Bollinger Bands and position size:

maPrice = sma(close, bolLength)
sdPrice = stdev(close, bolLength)

upperBand = maPrice + (sdOffset * sdPrice)
lowerBand = maPrice - (sdOffset * sdPrice)

orderSize = floor((0.50 * strategy.equity) / close)

We compute the moving average with sma(), a function that requires two arguments: a series of values to calculate on and the moving average length in number of bars (TradingView, n.d.). Here we use the function with the instrument’s closing prices (close) and bolLength, the input variable that has a standard value of 40. We store the simple moving average’s value in the maPrice variable for use later on.

Then we calculate a biased estimate of the standard deviation with stdev(), a function that uses a series of values alongside an integer that sets the number of bars to calculate on (TradingView, n.d.). Here we have it calculate with closing prices (close) for a bolLength number of bars. We assign the value returned by stdev() in sdPrice.

To calculate the upper Bollinger Band, we multiply the standard deviation (sdPrice) with the input variable that holds the standard deviation offset (sdOffset), and then add that to the maPrice variable. We assign the result to the upperBand variable to use later in the script. The value of the lowerBand variable calculates in the same way, except that here we subtract the standard deviation multiplied with its offset from the 40-bar SMA.

The next variable we compute here is orderSize, which we use later when submitting orders. To determine that order size, we multiply strategy.equity (a built-in variable that returns the sum of the strategy’s initial capital, net profit, and open profit; TradingView, n.d.) with 0.50. To determine how many contracts we can buy for 50% of the strategy’s equity, we divide that value with the instrument’s price (close).

To err on the safe side, we round the order size down to the nearest integer with floor(). So if the calculated order size is 4.82, floor(4.82) returns 4. This way our orders are always a little bit less than 50% of the strategy’s equity.

With the values computed, we plot the Bollinger Bands:

plot(series=upperBand, color=green, linewidth=2)
plot(series=maPrice, color=orange)
plot(series=lowerBand, color=red, linewidth=2)

The plot() function shows the data of its series argument on the chart, and displays that as a line by default (TradingView, n.d.).

The first plot() statement displays the upper Bollinger Band with that argument set to the upperBand variable. This plot’s colour is set to the green basic TradingView colour and linewidth, which specifies the plot’s width starting from 1 as the default size (TradingView, n.d.), makes the line a bit bigger than default with a value of 2.

The second plot() function call displays the SMA (series=maPrice) in the orange colour. With the third and last plot() function we plot the lower Bollinger Band (lowerBand) in the red standard TradingView colour, and this one also has a size that’s a bit bigger than default (linewidth=2).

Then we submit the orders for the long position:

strategy.entry(id="Enter Long", long=true, qty=orderSize, 
     when=crossover(close, upperBand))
     
strategy.close(id="Enter Long", when=crossunder(close, maPrice))

The strategy.entry() function opens a position with a market order by default (TradingView, n.d.). We use that function here with several arguments. With id we specify the order identifier, and this name displays on the chart and in the ‘Strategy Tester’ window but is also used by other functions to reference this order. With the long argument set to a value of true, strategy.entry() initiates a long position (TradingView, n.d.). And we set the order size with qty, for which we use our orderSize variable.

The when argument of strategy.entry(), when set to true, makes TradingView submit the entry order while the order won’t be send when this argument’s value is false. We send our enter long order whenever the crossover() function returns true on the current bar.

That crossover() function works on two series of values. It returns true when, on the current bar, the value of the first argument is greater than that of the second while, on the previous bar, the first argument’s value was below that of the second (TradingView, n.d.). When this upward cross didn’t happen, crossover() returns false.

The values that we use with crossover() are close and upperBand. This way the function returns true whenever the bar’s closing price crosses above the upper Bollinger Band. Since the when argument of strategy.entry() is then set to true, the strategy submits our enter long order. In all other cases (that is, when the closing price didn’t cross above the upper Bollinger Band), when is set to false and our enter long order isn’t submitted on that bar.

We close our long positions with strategy.close(), a function that exits a specific entry order with a market order (TradingView, n.d.). We specify which entry order to exit from with the function’s id argument, that we set to "Enter Long" here (the name of the market order that opened the long position). The when argument specifies the condition of this exit position command (TradingView, n.d.), and here we use the crossunder() function for that.

The crossunder() function works similar to crossover(). It returns true when, on the current bar, the value of the first argument is less than that of the second while, on the preceding bar, the first argument’s value was above that of the second (TradingView, n.d.). With the function using the close and maPrice values, we check whether the bar’s closing price dropped below the average of the upper and lower Bollinger Bands (stored in the maPrice variable). When that’s the case, crossunder() returns true. That makes the when argument of strategy.close() true too, causing our script to submit the exit long order.

The short position is managed in much the same way:

strategy.entry(id="Enter Short", long=false, qty=orderSize, 
     when=crossunder(close, lowerBand))
     
strategy.close(id="Enter Short", when=crossover(close, maPrice))

With strategy.entry() we submit a market order to open our short position (long=false). That order’s name is "Enter Short" and has the size we computed earlier (qty=orderSize). The true/false value returned by the crossunder() function (which uses the close and lowerBand values) determines when the strategy submits this order. This way our short order is send off whenever the current bar’s closing price drops below the lower Bollinger Band.

We exit short positions with strategy.close(), and the strategy submits those exit orders whenever the bar’s closing price has crossed above the midpoint line (crossover(close, maPrice)).

Example charts: the Bollinger Bands TradingView strategy

The example strategy we’ve created above has the following input options:

Input options of the TradingView example strategy

When we add the strategy to the chart, it generates trades like the following:

Example chart of the Bollinger Bands trading strategy in TradingView

The “Enter Short” and “Enter Long” trades on this chart both have a position size of 2 contracts. We calculated the size of these orders with the strategy’s equity, which started with an initial capital of 10,000 as set by the strategy() function:

strategy(title="Bollinger Bands breakout", overlay=true, 
     initial_capital=10000)

With those starting funds, our strategy achieved (excluding commission and slippage) a net loss of $379 alongside a drawdown of $4023:

Performance report of the Bollinger Bands trading strategy in TradingView

Our strategy’s largest position traded 4 contracts (the ‘Max Contracts Held’ row):

Performance summary of the Bollinger Bands trading strategy

Now let’s change the initial capital and see how that affects the chart and performance metrics. For that we change the initial_capital argument to 50,000:

strategy(title="Bollinger Bands breakout", overlay=true, 
     initial_capital=50000)

Without making other changes, we save the strategy and TradingView then reloads the script. Since we calculated the order size with the strategy’s equity (which is the sum of the initial capital, net profit, and open profit; TradingView, n.d.), our order size becomes bigger when the strategy’s initial capital increases:

Example chart with the Bollinger Bands strategy trading bigger positions

During the same time period as the previous chart, our strategy now trades orders with a size of 11 contracts. Since we had a losing strategy to begin with, increasing the initial capital (and thereby the order size) gives a bigger loss and deeper drawdown:

Performance overview of the Bollinger Bands strategy with more initial capital

The larger position size is also seen in the ‘Performance Summary’ tab of the ‘Strategy Tester’ window, which shows we now trade a maximum position of 30 contracts:

Performance summary of the Bollinger Bands strategy when trading more initial capital

Summary

Every TradingView strategy needs to use strategy(). That function allows us to configure several strategy properties, including its starting funds with the initial_capital argument. This argument influences how much cash the strategy has available during a backtest and forward test, but this script-specific value differs from the account balance of our paper trading or real broker account. When we don’t set initial_capital, the strategy’s initial capital defaults to 100,000. A strategy’s capital is denominated in the account’s currency. When that currency differs from the instrument we’re trading, TradingView performs a currency conversion. The initial capital affects the strategy’s relative performance and risk (like returns and drawdowns) but also the strategy’s equity, which is the sum of the initial capital, net profit, and open profit. That equity value is, for instance, used by TradingView when sizing orders based on an equity percentage.

Learn more:


References

“Admin” (2016, January 11). Issue with risk management on strategies (position sizing or pip risk). Retrieved on April 23, 2016, from https://getsatisfaction.com/tradingview/topics/issue-with-risk-management-on-strategies-position-sizing-or-pip-risk#reply_16502707

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

Pring, M.J. (2002). Technical Analysis Explained (4th edition). New York, NY: McGraw-Hill.

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