Grid Link: http://tos.mx/k3eswoE

You are using an out of date browser. It may not display this or other websites correctly.

You should upgrade or use an alternative browser.

You should upgrade or use an alternative browser.

- Thread starter sunnyr
- Start date

Grid Link: http://tos.mx/k3eswoE

http://traders.com/Documentation/FEEDbk_docs/2015/09/TradersTips.html

In “Decyclers” in this issue, author John Ehlers describes a method for constructing an oscillator that can help traders detect trend reversals with almost no lag. Ehlers calls this new oscillator a

For convenience, we are providing some EasyLanguage code for the simple decycler and decycler oscillator indicators based on Ehlers’ concepts. In addition, we are providing code for a TradeStation function to calculate the decycler oscillator, and a strategy that demonstrates the function’s usage.

Code:

```
// TASC Sep 2015
// Decyclers - John F. Ehlers
// Simple Decyclers
inputs:
HPPeriod( 125 ) ;
variables:
alpha1( 0 ),
HP( 0 ),
Decycle( 0 ) ;
// High Pass Filter
alpha1 = ( Cosine ( 0.707 * 360 / HPPeriod ) +
Sine( 0.707 * 360 / HPPeriod ) - 1 )
/ Cosine( .707 * 360 / HPPeriod ) ;
HP = ( 1 - alpha1 / 2 ) * ( 1 - alpha1 / 2 ) *
( Close - 2 * Close[1] + Close[2] ) + 2 *
( 1 - alpha1 ) * HP[1] - ( 1 - Alpha1 ) *
( 1 - alpha1 ) * HP[2] ;
Decycle = Close - HP ;
Plot1( Decycle, "DeCycle" ) ;
Plot2( 1.005 * Decycle, "UpperBand" ) ;
Plot3( 0.995 * Decycle, "LowerBand" ) ;
Indicator: Decycler Oscillator
// TASC Sep 2015
// Decyclers - John F. Ehlers
// Decycler Oscillator
inputs:
HPPeriod( 125 ),
K( 1 ) ;
variables:
alpha1( 0 ),
alpha2( 0 ),
HP( 0 ),
Decycle( 0 ),
DecycleOsc( 0 ) ;
alpha1 = ( Cosine ( 0.707 * 360 / HPPeriod ) +
Sine( 0.707 * 360 / HPPeriod ) - 1 )
/ Cosine( .707 * 360 / HPPeriod ) ;
HP = ( 1 - alpha1 / 2 ) * ( 1 - alpha1 / 2 ) *
( Close - 2 * Close[1] + Close[2] ) + 2 *
( 1 - alpha1 ) * HP[1] - ( 1 - Alpha1 ) *
( 1 - alpha1 ) * HP[2] ;
Decycle = Close - HP ;
alpha2 = ( Cosine( 0.707 * 360 / ( 0.5 * HPPeriod ) )
+ Sine( 0.707 * 360 / ( 0.5 * HPPeriod ) ) - 1) /
Cosine( 0.707 * 360 / ( 0.5 * HPPeriod ) ) ;
DecycleOsc = ( 1 - alpha2 / 2 ) * ( 1 - alpha2 / 2 ) *
( Decycle - 2 * Decycle[1] + Decycle[2] ) + 2 *
( 1 - alpha2 ) * DecycleOsc[1] - ( 1 - alpha2 ) *
( 1 - alpha2 ) * DecycleOsc[2] ;
Plot1( 100 * K * DecycleOsc / Close, "DecycleOsc" ) ;
Plot2( 0, "ZeroLine" ) ;
Function: DecyclerOscillator
// TASC Sep 2015
// Decyclers - John F. Ehlers
// Decycler Oscillator Function
inputs:
Price( NumericSeries ),
HPPeriod( NumericSimple ),
K( NumericSimple ) ;
variables:
alpha1( 0 ),
alpha2( 0 ),
HP( 0 ),
Decycle( 0 ),
DecycleOsc( 0 ) ;
// High Pass Filter
alpha1 = ( Cosine ( 0.707 * 360 / HPPeriod ) +
Sine( 0.707 * 360 / HPPeriod ) - 1 ) /
Cosine( .707 * 360 / HPPeriod ) ;
HP = ( 1 - alpha1 / 2 ) * ( 1 - alpha1 / 2 ) *
( Price - 2 * Price[1] + Price[2] ) + 2 *
( 1 - alpha1 ) * HP[1] - ( 1 - Alpha1 ) *
( 1 - alpha1 ) * HP[2] ;
Decycle = Price - HP ;
alpha2 = ( Cosine( 0.707 * 360 / ( 0.5 * HPPeriod ) )
+ Sine( 0.707 * 360 / ( 0.5 * HPPeriod ) ) - 1) /
Cosine( 0.707 * 360 / ( 0.5 * HPPeriod ) ) ;
DecycleOsc = ( 1 - alpha2 / 2 ) * ( 1 - alpha2 / 2 ) *
( Decycle - 2 * Decycle[1] + Decycle[2] ) + 2 *
( 1 - alpha2 ) * DecycleOsc[1] - ( 1 - alpha2 ) *
( 1 - alpha2 ) * DecycleOsc[2] ;
DecyclerOscillator = 100 * K * DecycleOsc / Price ;
Strategy: Decycler Oscillator
// TASC Sep 2015
// Decyclers - John F. Ehlers
// Decycler Oscillator Strategy
inputs:
Price( Close ),
Fast_HPPeriod( 100 ),
Fast_K( 1.2 ),
Slow_HPPeriod( 125 ),
Slow_K( 1 ) ;
variables:
Fast_Val( 0 ),
Slow_Val( 0 ) ;
Fast_Val =
DecyclerOscillator( Price, Fast_HPPeriod, Fast_K ) ;
Slow_Val =
DecyclerOscillator( Price, Slow_HPPeriod, Slow_K ) ;
if Fast_Val crosses over Slow_Val then
Buy next bar at Market
else if Slow_Val crosses over Fast_Val then
SellShort next bar at Market ;
```

Code:

```
variables:
PlotDots(true),
LookBack(4),
Offset(.25);
if low < low[1] and close >= low + .5 * Range then
begin
if CountIf(low < low[1],LookBack + 1) = LookBack + 1
then plot2(low - Offset * Average(Range,10),"Long+")
else if PlotDots then plot1(low - Offset * Average(Range,10),"Long");
end;
```

@pfriedl I'm guessing this 1272 page pdf is the most complete EasyLanguage reference available. https://uploads.tradestation.com/uploads/EasyLanguage-Functions-and-Reserved-Words-Reference.pdf

That code snippet isn't using any reserved words though except CountIf which works how you'd expect based on that code. It's being used to check if a condition is true on every bar for the last x bars. Then the code updates one plot or the other. If you need the look back to be a dynamic length using an input you'd need to use fold to loop. If a static length is fine then the code is simpler.

I think this is equivalent but definitely review/proofread this and test it thoroughly. It should at least get you close to what you need. Note that because of the .5 * range in that code the condition is only true on things that move enough in one candle, like /ES or other high priced tickers or using longer timeframes. Testing it on low price stocks on short timeframes it'll never be true.

That code snippet isn't using any reserved words though except CountIf which works how you'd expect based on that code. It's being used to check if a condition is true on every bar for the last x bars. Then the code updates one plot or the other. If you need the look back to be a dynamic length using an input you'd need to use fold to loop. If a static length is fine then the code is simpler.

I think this is equivalent but definitely review/proofread this and test it thoroughly. It should at least get you close to what you need. Note that because of the .5 * range in that code the condition is only true on things that move enough in one candle, like /ES or other high priced tickers or using longer timeframes. Testing it on low price stocks on short timeframes it'll never be true.

Ruby:

```
input PlotDots = yes;
#input LookBack = 4;
input Offset = .25;
# example code has a Range variable but its
# definition isn't included in the example
def Range = 1;
script lowMeetsCriteria {
input index = 1;
input range = 1;
plot result = low < low[index] and close >= low + .5 * range;
}
def result =
lowMeetsCriteria(1, Range)
and lowMeetsCriteria(2, Range)
and lowMeetsCriteria(3, Range)
and lowMeetsCriteria(4, Range)
;
def value = low - Offset * Average(Range, 10);
plot p1 = if result != 1 then if PlotDots == 1 then value else Double.NaN else Double.NaN;
p1.SetDefaultColor(Color.WHITE);
p1.SetPaintingStrategy(PaintingStrategy.POINTS);
plot p2 = if result == 1 then value else Double.NaN;
p2.SetDefaultColor(Color.YELLOW);
```

Last edited:

Range is a function in TS: http://help.tradestation.com/10_00/eng/tsdevhelp/elword/function/range_function_.htm?Highlight=range

"The Range function subtracts the Low of a bar from the High to determine the range of the bar." so if the low was 100 and the high was 102, then the Range would end up being102-100 = 2.

From the definition of Low() http://help.tradestation.com/10_00/eng/tsdevhelp/elword/word/low_reserved_word_.htm?Highlight=low

Code:

`if low < low[1] and close >= low + .5 * Range then begin ... end;`

is only comparing the current candle "low" to the last candle "low[1]" and if it's lower and the last candle close is greater than the current low + half the current range, then the conditional would be true and it would continue into the nested if statement.

Once it passes that initial test, we hit the CountIf. and CountIf looks like it actually returns the number of times a statement is true over N candles as opposed to returning true/false if all or none of the conditions were met.

So whether that test fails or not, it's still rendering a plot, but with just a difference in the label (Long vs Long+)?

Ruby:

```
input PlotDots = yes;
input Offset = .25;
def range = high - low;
def result =
low < low[1] and close >= low + .5 * range
and low[1] < low[2]
and low[2] < low[3]
and low[3] < low[4]
and low[4] < low[5]
;
def value = low - Offset * Average(range, 10);
plot p1 = if result != 1 then if PlotDots == 1 then value else Double.NaN else Double.NaN;
p1.SetDefaultColor(Color.WHITE);
p1.SetPaintingStrategy(PaintingStrategy.POINTS);
plot p2 = if result == 1 then value else Double.NaN;
p2.SetDefaultColor(Color.YELLOW);
p2.SetLineWeight(3);
```

Yes, exactly. Making sure it's been in a down trend to reverse from. It looks like it may work well when the trend isn't stronger than usual. I gave it a name and kept it. I'll probably throw it on some charts and keep an eye on it to see how well it works.CountIf is basically looking for 5 straight bars of lower lows in order to show maybe a stronger potential for reversal? Not sure.

Code:

```
{StoRSI}
inputs: RSILen(13), StoLen(21), MA(3), MA2(5);
vars: PV(0), pvt(0), pvb(0);
vars: OverBought(80), OverSold(20), Middle (50);
Vars: Sum(0), Counter(0);
pvt = RSI(Close, RSILen) - Lowest(RSI(Close, RSILen), STOLen);
pvb = Highest(RSI(Close, RSILen), STOLen) - Lowest(RSI(Close, RSILen), STOLen);
Sum = 0;
For counter = 0 To MA - 1 Begin
pvt = (RSI(Close, RSILen) - Lowest(RSI(Close, RSILen), STOLen)) of counter bars ago;
pvb = (Highest(RSI(Close, RSILen), STOLen) - Lowest(RSI(Close, RSILen), STOLen)) of counter bars ago;
PV = iff(pvb > 0, pvt/pvb, 0);
Sum = Sum + PV;
End;
PV = iff(MA > 0, Sum / MA, 0);
plot1(PV*100, "StoRSI");
plot2(average(PV,MA2)*100, "StoRSI2");
plot3(OverBought, "OB");
plot4(OverSold, "OS");
Plot5(Middle, "M");
```

Thread starter | Similar threads | Forum | Replies | Date |
---|---|---|---|---|

W | TradeStation Conversion | Questions | 8 | |

R | Pull full order book into thinkscript | Questions | 2 | |

S | Ford Equity Research Bands In ThinkScript | Questions | 27 | |

N | Thinkscript - Stop trading after first loss | Questions | 3 | |

T | ThinkScript strategy orders seem off | Questions | 5 |