TASC 2020-08 | Tracking Relative Strength In Four Dimensions (RS4r) (Garofallou)

Modified on 2020/07/30 09:51 by Eugene — Categorized as: TASC Traders Tips

Traders' Tip text

In this month's Tip space we show how to screen for symbols that meet a specified criteria as of the most recent date. The criteria here is the value of an oscillator like RS4 or RS5: the strongest ranked funds get the preference.

To set things up, first have your index funds (or whatever instruments required) in a Wealth-Lab DataSet and update their data. Then in the screener code, type in your symbol names instead of author's choice of funds:

{"FXAIX", "FNCMX", "FSMDX", "FSSNX", "FSPGX", "FLCOX", "FPADX", "FSRNX", "FSAGX", "FSUTX", "FTBFX"};
By running the screener below on a DataSet of chosen symbols in portfolio backtest mode, you'll get a list of signals to buy on the open in the Alerts view as on Figure 1:


Image

Figure 1. A view of the Alerts tab with 2 signals with the highest reading of the RS5 oscillator.


If you wish to visualize the oscillators, double click on any trading signal. Wealth-Lab will plot them on a chart like Figure 2 illustrates:


Image

Figure 2. A sample plot of the RS4 and RS5 oscillators built using author’s default set of 11 index funds on the daily chart of QQQ. Index fund data provided by Tiingo.


On a closing note, simply download public strategies from Wealth-Lab (hit Ctrl-O and choose "Download...") to get the trading system code below:

WealthScript Code (C#)

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;

namespace WealthLab.Strategies { public class TASC2020_09 : WealthScript { LineStyle ls = LineStyle.Solid; public DataSeries RS2t(DataSeries ds, string index, int period = 10, bool plotSeries = false) { var rs = new DataSeries(ds, string.Format("RS2t({0},{1},{2}", ds.Description, index, period)); var extSym = GetExternalSymbol(index, true); var RS1 = ds / extSym.Close;

var Fast = EMAModern.Series(RS1, period); //Fast MA: Orange var Med = SMA.Series(Fast, 7); //Medium MA: Green var Slow = SMA.Series(Fast, 15); //Slow MA: Red var Vslow = SMA.Series(Slow, 30); //V Slow MA: Blue

int Tier1 = 0, Tier2 = 0, Tier3 = 0, Tier4 = 0;

for (int bar = GetTradingLoopStartBar(Math.Max(period * 3, 30)); bar < ds.Count; bar++) { Tier1 = (Fast[bar] >= Med[bar] && Med[bar] >= Slow[bar] && Slow[bar] >= Vslow[bar]) ? 10 : 0; Tier2 = (Fast[bar] >= Med[bar] && Med[bar] >= Slow[bar] && Slow[bar] < Vslow[bar]) ? 9 : 0; Tier3 = (Fast[bar] < Med[bar] && Med[bar] >= Slow[bar] && Slow[bar] >= Vslow[bar]) ? 9 : 0; Tier4 = (Fast[bar] < Med[bar] && Med[bar] >= Slow[bar] && Slow[bar] < Vslow[bar]) ? 5 : 0;

rs[bar] = Tier1 + Tier2 + Tier3 + Tier4; }

if (plotSeries) { var rp = CreatePane(50, false, true); PlotSeries(rp, RS1, Color.Black, ls, 1); PlotSeries(rp, Fast, Color.DarkOrange, ls, 2); PlotSeries(rp, Med, Color.MediumSeaGreen, ls, 2); PlotSeries(rp, Slow, Color.Crimson, ls, 2); PlotSeries(rp, Vslow, Color.SteelBlue, ls, 2); }

return rs; }

protected override void Execute() { int period = 10; var lstIndices = new List<string>() { "FXAIX", "FNCMX", "FSMDX", "FSSNX", "FSPGX", "FLCOX", "FPADX", "FSRNX", "FSAGX", "FSUTX", "FTBFX"};

var RS3x = Close * 0; foreach (var fund in lstIndices) { RS3x += RS2t(Close, fund, period); }

var RS4 = (RS3x / lstIndices.Count) * 10; //Scaled to 0 to 100 for (int bar = 0; bar < RS4.Count; bar++) RS4[bar] = Math.Round(RS4[bar]); var RS4osc = SMA.Series(RS4, 3); //RS oscillator var Mv = SMA.Series(RS4osc, 5); //RSosc's signal line

var rp = CreatePane(40, false, true); PlotSeries(rp, RS4osc, Color.DarkSlateBlue, ls, 2, "RS4r Oscillator"); PlotSeries(rp, Mv, Color.Crimson, ls, 2, "SMA5"); HideVolume();

DrawHorzLine(rp, 80, Color.Red, LineStyle.Dashed, 1); DrawHorzLine(rp, 100, Color.Black, LineStyle.Dashed, 1);

var mvRS4 = WMA.Series(RS4, 4); //Moving Avg of RS4r var R5 = new DataSeries(Close, string.Format("R5({0})",period)); var x = Open * 0; for (int bar = 1; bar < RS4.Count; bar++) { bool RS4up = (RS4[bar] >= 80 || RS4[bar] > mvRS4[bar]); //RS4r is above signal line x[bar] = RS4[bar] >= 80 ? 1 : 0; //RS4r must be >= 80 }

//Avg of >80 scores in period for (int bar = 1; bar < RS4.Count; bar++) R5[bar] = (Sum.Series(x, period)[bar] / period) * 100;

var rp5 = CreatePane(20, false, true); PlotSeries(rp5, R5, Color.Red, ls, 2, "R5");

int b = Bars.Count - 1; if (b < Math.Max(period * 3, 30)) return; //if ( RS4osc[b] > 80 ) BuyAtMarket(b + 1, Math.Round(RS4osc[b]).ToString()); if ( R5[b] > 80 ) BuyAtMarket(b + 1, Math.Round(R5[b]).ToString()); } } }

Gene Geren (Eugene)
Wealth-Lab team