Indicators

Combining Indicators

Introduction

Indicator extensions let you chain indications together like Lego blocks to create unique combinations. When you chain indicators together, the .Current.Value output of one indicator is the input of the following indicator. To chain indicators together with values other than the .Current.Value, create a custom indicator.

Addition

The Plus extension sums the .Current.Value of two indicators or sums the .Current.Value of an indicator and a fixed value.

// Sum the output of two indicators
var rsiShort = RSI("SPY", 14);
var rsiLong = RSI("SPY", 21);
var rsiPlusRsi = rsiShort.Plus(rsiLong);

// Sum the output of an indicator and a fixed value
var rsiPlusValue = rsiShort.Plus(10);
# Sum the output of two indicators
rsi_short = self.rsi("SPY", 14)
rsi_long = self.rsi("SPY", 21)
rsi_plus_rsi = IndicatorExtensions.plus(rsi_short, rsi_long)

# Sum the output of an indicator and a fixed value
rsi_plus_value = IndicatorExtensions.plus(rsi_short, 10)

If you pass an indicator to the Plus extension, you can name the composite indicator.

var namedIndicator = rsiShort.Plus(rsiLong, "RSI Sum");
named_indicator = IndicatorExtensions.plus(rsi_short, rsi_long, "RSI Sum")

Subtraction

The Minus extension subtracts the .Current.Value of two indicators or subtracts a fixed value from the .Current.Value of an indicator.

// Subtract the output of two indicators
var smaShort = SMA("SPY", 14);
var smaLong = SMA("SPY", 21);
var smaDifference = smaShort.Minus(smaLong);

// Subtract a fixed value from the output of an indicator
var smaMinusValue = smaShort.Minus(10);
# Subtract the output of two indicators
sma_short = self.sma("SPY", 14)
sma_long = self.sma("SPY", 21)
sma_difference = IndicatorExtensions.minus(sma_short, sma_long)

# Subtract a fixed value from the output of an indicator
sma_minus_value = IndicatorExtensions.minus(sma_short, 10)

If you pass an indicator to the Minus extension, you can name the composite indicator.

var namedIndicator = smaShort.Minus(smaLong, "SMA Difference");
named_indicator = IndicatorExtensions.minus(sma_short, sma_long, "SMA Difference")

Multiplication

The Times extension multiplies the .Current.Value of two indicators or multiplies a fixed value and the .Current.Value of an indicator.

// Multiply the output of two indicators
var emaShort = EMA("SPY", 14);
var emaLong = EMA("SPY", 21);
var emaProduct = emaShort.Times(emaLong);

// Multiply the output of an indicator and a fixed value
var emaTimesValue = emaShort.Times(10);
# Multiply the output of two indicators
ema_short = self.ema("SPY", 14)
ema_long = self.ema("SPY", 21)
ema_product = IndicatorExtensions.times(ema_short, ema_long)

# Multiply the output of an indicator and a fixed value
ema_times_value = IndicatorExtensions.times(ema_short, 1.5)

If you pass an indicator to the Times extension, you can name the composite indicator.

var namedIndicator = emaShort.Times(emaLong, "EMA Product");
named_indicator = IndicatorExtensions.times(ema_short, ema_long, "EMA Product")

Division

The Over extension divides the .Current.Value of an indicator by the .Current.Value of another indicator or a fixed value.

// Divide the output of two indicators
var rsiShort = RSI("SPY", 14);
var rsiLong = RSI("SPY", 21);
var rsiDivision = rsiShort.Over(rsiLong);

// Divide the output of an indicator by a fixed value
var rsiAverage = rsiShort.Plus(rsiLong).Over(2);
# Divide the output of two indicators
rsi_short = self.rsi("SPY", 14)
rsi_long = self.rsi("SPY", 21)
rsi_division = rsi_short.over(rsi_long)

# Divide the output of an indicator by a fixed value
rsi_half = IndicatorExtensions.over(rsi_short, 2)

If you pass an indicator to the Over extension, you can name the composite indicator.

var namedIndicator = rsiShort.Over(rsiLong, "RSI Division");
named_indicator = IndicatorExtensions.over(rsi_short, rsi_long, "RSI Division")

Weighted Average

The WeightedBy extension calculates the average .Current.Value of an indicator over a lookback period, weighted by another indicator over the same lookback period. The value of the calculation is

$$ \frac{\textbf{x} \cdot \textbf{y}}{ \sum\limits_{i=1}^{n} y_{i} } $$

where $\textbf{x}$ is a vector that contains the historical values of the first indicator, $\textbf{y}$ is a vector that contains the historical values of the second indicator, and $n$ is the lookback period.

var smaShort = SMA("SPY", 14); 
var smaLong = SMA("SPY", 21); 
var weightedSMA = smaShort.WeightedBy(smaLong, 3);
sma_short = self.sma("SPY", 14)
sma_long = self.sma("SPY", 21)
weighted_sma = IndicatorExtensions.weighted_by(sma_short, sma_long, 3)

Custom Chains

The Of extension feeds an indicator's .Current.Value into the input of another indicator. The first argument of the IndicatorExtensions.Of method must be a manual indicator with no automatic updates. If you pass an indicator that has automatic updates as the argument, that first indicator is updated twice. The first update is from the security data and the second update is from the IndicatorExtensions class.

var rsi = RSI("SPY", 14);
var rsiSMA = (new SimpleMovingAverage(10)).Of(rsi); // 10-period SMA of the 14-period RSI
rsi = self.rsi("SPY", 14)
rsi_sma = IndicatorExtensions.of(SimpleMovingAverage(10), rsi) # 10-period SMA of the 14-period RSI

If you pass a manual indicator as the second argument, to update the indicator chain, update the second indicator. If you call the Updateupdate method of the entire indicator chain, it won't update the chain properly.

Simple Moving Average

The SMA extension calculates the simple moving average of an indicator's .Current.Value.

var rsi = RSI("SPY", 14); // Create a RSI indicator
var rsiSMA = rsi.SMA(3); // Create an indicator to calculate the 3-period SMA of the RSI indicator
rsi = self.rsi("SPY", 14) # Create a RSI indicator
rsi_sma = IndicatorExtensions.SMA(rsi, 3) # Create an indicator to calculate the 3-period SMA of the RSI indicator

Exponential Moving Average

The EMA extension calculates the exponential moving average of an indicator's .Current.Value.

var rsi = RSI("SPY", 14); // Create a RSI indicator
var rsiEMA = _rsi.EMA(3); // Create an indicator to calculate the 3-period EMA of the RSI indicator
rsi = self.rsi("SPY", 14) # Create a RSI indicator
rsi_ema = IndicatorExtensions.EMA(rsi, 3) # Create an indicator to calculate the 3-period EMA of the RSI indicator

The EMA extension can also accept a smoothing parameter that sets the percentage of data from the previous value that's carried into the next value.

var rsiEMA = rsi.EMA(3, 0.1m); // 10% smoothing factor
rsi_ema = IndicatorExtensions.EMA(rsi, 3, 0.1) # 10% smoothing factor

Maximum

The MAX extension calculates an indicator's maximum .Current.Value over a lookback window.

var ema = EMA("SPY", 14); // Create an EMA indicator
var emaMax = ema.MAX(10); // Create an indicator to calculate the maximum EMA over the last 10 periods
ema = self.ema("SPY", 14) # Create an EMA indicator
ema_max = IndicatorExtensions.MAX(ema, 10) # Create an indicator to calculate the maximum EMA over the last 10 periods

Minimum

The MIN extension calculates an indicator's minimum .Current.Value over a lookback window.

var ema = EMA("SPY", 14); // Create an EMA indicator
var emaMin = ema.MIN(10); // Create an indicator to calculate the minimum EMA over the last 10 periods
ema = self.ema("SPY", 14) # Create an EMA indicator
ema_min = IndicatorExtensions.MIN(ema, 10) # Create an indicator to calculate the minimum EMA over the last 10 periods

Examples

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: