Returning Tuples


This tutorial we takes a closer look at the popular MACD and Bollinger Bands indicators. Both indicators are composed of multiple series that are returned as a single object of type  series_tuple<T>. Let's first take a look at the MACD. It consists of two moving averages, a signal line, and a histogram. 

 

Extract from Tutorial 210:

 

series_tuple<double> MACD_DEMO( sref<double> close, size_t period_short

                         size_t period_long, size_t period_signal)

{

          auto ma_short  = EMA(close, period_short);      // short period moving average

          auto ma_long   = EMA(close, period_long);       // long period moving average

          auto macd_line = ma_short - ma_long;            // difference between averages

          auto signal    = EMA(macd_line, period_signal); // MACD signal

          auto histo     = signal - macd_line;            // MACD histogram

 

          series_tuple<double> tuple = {    // return value is tuple of series

 

         macd_line.name("macd").plot_as("MACD", {  period_short, period_long },

               plot_type::line, color::blue),

 

         signal.name("signal").plot_as("MACD-SIG"period_signal,

               plot_type::line, color::white),

 

         histo.name("hist").plot_as("MACD-HIST", 0, 

               plot_type::bar, color::green),

          };

 

          return tuple;

}

 

 

 

 

 

 

 

Chart produced by tutorial 210:

 

Program Output:

 

Accessing Series in Series Tuples


Lets have a look at how we would access series references that are themselves elements in a tuple object. In DSL, each series can simply be accessed by its name. Doing so has no impact on performance since DSL code is not evaluated repeatedly. We simply write:

 

                    void on_prepare(voidoverride

                    {

                              macd = MACD_DEMO(in.close, 12, 24, 9);  // 'macd' is a strategy member

 

                              auto signal    = macd("signal");   // access to individual tuple elements

                              auto macd_line = macd("macd");

                              auto macd_hist = macd("hist");

                    }

 

Performance is more of an issue when defining strategy::on_bar_close(), as it is called repeatedly for every bar. Although access to tuple elements by name is also possible, it is preferable to access values by ordinal position such as in:

 

                    void on_bar_close(void)     override

                    {

                              const size_t macd_line_pos = 0;

                              const size_t macd_signal_pos = 1;

                              const size_t macd_histo_pos = 2;

 

                              double macd_line   = macd[macd_line_pos][0];

                              double macd_signal = macd[macd_signal_pos][0];

                              double macd_histo  = macd[macd_histo_pos][0];

                    }

Bollinger Bands


The popular Bollinger Bands function is another example of a function returning a tuple.  The Bollinger Band concept is relatively simple. First, calculate a moving average, then add two bands, one above and one below the moving average, both at a distance defined by the standard deviation of price over the given period, multiplied by a given constant. Bollinger Bands can be used both as the basis for breakout systems as well as for mean reversion systems.

 

Extract from Tutorial 211.

 

 

series_tuple<double> BOLLINGER_BANDS_DEMO(

          series_cref<double> hi, series_cref<double> lo,

          series_cref<double> cl, size_t period, double std_dev_mult)

{

          auto tp     = TYPICAL_PRICE(hi, lo, cl);

          auto avg    = SMA(tp, period);

          auto offset = STDEVP(tp, period) * std_dev_mult;

          auto upper  = avg + offset;

          auto lower  = avg - offset;

 

          series_tuple<double> tuple = {

                    upper.name("upper").plot_as("BB_U", std_dev_mult, plot_type::line, color::green),

                    avg.name("avg").plot_as("BB_AVG", period, plot_type::line, color::white),

                    lower.name("lower").plot_as("BB_L", std_dev_mult, plot_type::line, color::green)

          };

          return tuple;

}

 

Chart produced by tutorial 211:

 

Program Output: