Welcome Guest, please sign in to participate in a discussion. Search | Active Topics |

TASC Jan 2015: Universal Indicator Rate this Topic:
Previous Topic · Next Topic Watch this topic · Print this topic ·
haschade
Posted : Friday, July 31, 2015 11:39:00 AM
Registered User
Joined: 8/21/2007
Posts: 181
In “Whiter Is Brighter,” author John Ehlers presents a new indicator he calls the
universal oscillator. It is based on his theory that market data resembles pink noise,
or as he puts it, “noise with memory.”
In his article, Ehlers has already provided some TradeStation code for his ultimate oscillator
that could be used to create a short-term trading strategy.  Can this be "ported" to StockFinder?
 
The code is also shown below:
 
_Ehlers_Universal Oscillator (Indicator)
 
// Universal Oscillator
// (c) 2014 John F. Ehlers
// TASC January 2015
inputs:
 BandEdge( 20 ) ;
variables:
 WhiteNoise( 0 ),
 a1( 0 ),
 b1( 0 ),
 c1( 0 ),
 c2( 0 ),
 c3( 0 ),
 Filt(0),
 Peak(0),
 Universal( 0 ) ;
 
once
 begin
 if BandEdge <= 0 then
  RaiseRunTimeError( "BandEdge must be > zero" ) ;
 end ;
 
WhiteNoise = ( Close - Close[2] ) / 2 ;
 
// SuperSmoother Filter
a1 = ExpValue( -1.414 * 3.14159 / BandEdge ) ;
b1 = 2 * a1 * Cosine( 1.414 * 180 / BandEdge ) ;
c2 = b1 ;
c3 = -a1 * a1 ;
c1 = 1 - c2 - c3 ;
Filt = c1 * ( WhiteNoise + WhiteNoise [1] ) / 2 +
c2 * Filt[1] + c3 * Filt[2] ;
If Currentbar = 1 then
 Filt = 0 ;
If Currentbar = 2 then
 Filt = c1 * 0 * ( Close + Close[1] ) / 2 + c2 * Filt[1] ;
If Currentbar = 3 then
 Filt = c1 * 0 * ( Close + Close[1] ) / 2 + c2 * Filt[1] +
c3 * Filt[2] ;
 
// Automatic Gain Control (AGC)
Peak = .991 * Peak[1] ;
If Currentbar = 1 then
 Peak = .0000001 ;
If AbsValue( Filt ) > Peak then
 Peak = AbsValue( Filt ) ;
If Peak <> 0 then
 Universal = Filt / Peak ;
Plot1( Universal ) ;
Plot2( 0 ) ;
**    ------------------ */

 

Bruce_L
Posted : Friday, July 31, 2015 1:29:52 PM


Worden Trainer

Joined: 10/7/2004
Posts: 65,138

I tried just converting it pretty much verbatim, but I'm not getting a plot. This is despite doing things like converting the cosine from degrees to radians.

I may have to find and look at the original article. There is some math in there that just doesn't make sense.

Filt = c1 * 0 * ( Close + Close[1] ) / 2 + c2 * Filt[1] + c3 * Filt[2] ;

Like what is the point of the c1 * 0 * (Close + Close[1]) / 2 portion of that? Multiplying anything by zero is just going to produce zero. But it seems strange for it to be in the code if it doesn't do anything.

Then again the code calculates b1, assigns it to c2 and never uses b1 again and that doesn't seem to have a point, so maybe it is just strangely written.



-Bruce
Personal Criteria Formulas
TC2000 Support Articles
diceman
Posted : Friday, July 31, 2015 3:35:43 PM
Registered User
Joined: 1/28/2005
Posts: 6,049


For the record, I tried this code and it works in TS.

 

 

 

Thanks

 

Bruce_L
Posted : Friday, July 31, 2015 3:52:28 PM


Worden Trainer

Joined: 10/7/2004
Posts: 65,138

The formulas with the 0 factor in them would still produce numbers. It is just that it seems to me there are unneccessary calculations in the formulas that don't actually do anything. It could be that I'm just not understanding the code. If those sections are doing something then I definitely don't understand the code.

So when I read through the article, I should have a better idea of what it is supposed to do. Which should allow me to write RealCode that actually works.



-Bruce
Personal Criteria Formulas
TC2000 Support Articles
haschade
Posted : Monday, August 3, 2015 10:29:22 AM
Registered User
Joined: 8/21/2007
Posts: 181

If it is any help, here is another version.

// Universal Oscillator
// (c) 2014 John F. Ehlers
// TASC January 2015
// mapped to C# for WhenToTrade platform by LvT
 
using System;
 
namespace WTTScripting
{
public partial class Indicator
{
///<scriptname>
///Ehlers Universal Oscillator
///</scriptname>
///<param>
///Length(20)
///</param>
///<plotfuture>
///false
///</plotfuture>
///<summary>
///Plots universal oscillator
///as shown in TASC January 2015
///</summary>
public static double[] UNIOSC(double[] source, string stringParam)
{
//---- Define general script parameters
int currentbar = 1; // barcounter 
int Bars = source.Length; // length of source dataset (bars)
double[] returnvalues = new double[source.Length]; // init of return dataset
 
//---- Define individual script parameters
double WhiteNoise, a1, b1, c1, c2, c3, Filt, Peak, Universal;
double prevWhiteNoise1, prevFilt1, prevFilt2, prevPeak1; //used to store previous values
 
//----  Parse script input parameters "xxx,xxx,xxx,xxx"
int BandEdge; // individual parameter from individual settings
string[] param = stringParam.Split(',');
int.TryParse(param[0], out BandEdge);
 
//---- set initial values
WhiteNoise = Filt = Peak = prevFilt1 = Universal = 0;
if (BandEdge == 0) BandEdge = 20;
// initialize first indicator values for return dataset with zero
for (int z = 1; z <= BandEdge + 2; z++) returnvalues[Bars - z] = 0.0;
 
//---- Loop over dataset and do script calculation
int i = Bars-3;
while (i >= 0)
{
//save previous values
prevWhiteNoise1 = WhiteNoise;
prevFilt2 = prevFilt1;
prevFilt1 = Filt;
prevPeak1 = Peak;
 
//start calculation
WhiteNoise = (source[i] - source[i+2]) / 2;
 
// SuperSmoother Filter
a1 = ExpValue(-1.414 * 3.14159 / BandEdge);
b1 = 2 * a1 * Cosine(1.414 * 180 / BandEdge);
c2 = b1;
c3 = -a1 * a1;
c1 = 1 - c2 - c3;
Filt = c1 * (WhiteNoise + prevWhiteNoise1) / 2 + c2 * prevFilt1 + c3 * prevFilt2;
if (currentbar == 1) Filt = 0;
if (currentbar == 2) Filt = c1 * 0 * (source[i] + source[i+1]) / 2 + c2 * prevFilt1;
if (currentbar == 3) Filt = c1 * 0 * (source[i] + source[i+1]) / 2 + c2 * prevFilt1 + c3 * prevFilt2;
 
// Automatic Gain Control (AGC)
Peak = .991 * prevPeak1;
if (currentbar == 1) Peak = .0000001;
if (AbsValue(Filt) > Peak) Peak = AbsValue(Filt);
if (Peak!= 0) Universal = Filt / Peak;
 
//Write back final return value
returnvalues[i] = Universal;
 
currentbar++;
i--;
}
 
return returnvalues;
}
// end individual script indicator function
}
// end of indicator class
}
// end of namespace WTTScripting
 
haschade
Posted : Monday, August 10, 2015 11:01:22 AM
Registered User
Joined: 8/21/2007
Posts: 181

Just wondering if anyone had any success creating this...

Bruce_L
Posted : Thursday, August 13, 2015 2:17:39 PM


Worden Trainer

Joined: 10/7/2004
Posts: 65,138

Please try the following RealCode Indicator.

'|******************************************************************
'|*** StockFinder RealCode Indicator - Version 5.0 www.worden.com 
'|*** Copy and paste this header and code into StockFinder *********
'|*** Indicator:Universal Oscillator
'|******************************************************************
'#Cumulative
'# BandEdge = UserInput.Single = 20
Static WhiteNoise As New List(Of Single)
Static a1 As Single
Static b1 As Single
Static c1 As Single
Static c2 As Single
Static c3 As Single
Static Filt As New List(Of Single)
Static Peak As Single
Static Universal As Single
If isFirstBar Then
	WhiteNoise.Clear
	Dim pi As Single = Math.Acos(-1)
	Dim r2 As Single = Math.Sqrt(2)
	a1 = Math.Exp(-r2 * pi / BandEdge)
	b1 = 2 * a1 * Math.Cos(r2 * pi / BandEdge)
	c2 = b1
	c3 = -a1 * a1
	c1 = 1 - c2 - c3
	Filt.Clear
	Filt.Insert(0, 0)
	Peak = .0000001
	Universal = 0
Else If CurrentIndex = 1 Then
	Filt.Insert(0, 0)
	Filt(0) = c1 * 0 * (Price.Close + Price.Close(1)) / 2 + c2 * Filt(1)
Else If CurrentIndex = 2 Then
	WhiteNoise.Insert(0, (Price.Close - Price.Close(2)) / 2)
	Filt.Insert(0, 0)
	Filt(0) = c1 * 0 * (Price.Close - Price.Close(1)) / 2 + c2 * Filt(1) + c3 * Filt(2)
Else
	WhiteNoise.Insert(0, (Price.Close - Price.Close(2)) / 2)
	Filt.Insert(0, 0)
	Filt(0) = c1 * (WhiteNoise(0) + WhiteNoise(1)) / 2 + c2 * Filt(1) + c3 * Filt(2)
End If
Peak = .991 * Peak
If Math.Abs(Filt(0)) > Peak Then Peak = Math.Abs(Filt(0))
If Peak <> 0 Then Universal = Filt(0) / Peak
Plot = Universal
If isLastBar Then
	WhiteNoise.Clear
	Filt.Clear
End If


-Bruce
Personal Criteria Formulas
TC2000 Support Articles
haschade
Posted : Thursday, August 13, 2015 2:54:49 PM
Registered User
Joined: 8/21/2007
Posts: 181

Bruce,

First, thanks for this -- very much.  I appreciate it.

Second, it mostly  works.

On short BandEdge values (<44) it behaves just like on 2 other platforms.  However, on values higher (like 81, a standard), it is wildly different.  On other platforms, 81 is a smooth, slow moving value.  This cost is highly eratic, even more sensitive than a value of 20.

If anyone could look into it, I'd appreciate it.

Many thanks again.

Bruce_L
Posted : Thursday, August 13, 2015 3:09:28 PM


Worden Trainer

Joined: 10/7/2004
Posts: 65,138

I think it was a degrees/radians thing, but I don't have any values against which to compare. Please give it another try.



-Bruce
Personal Criteria Formulas
TC2000 Support Articles
Users browsing this topic
Guest-1

Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.