November 2008
TRADERS' TIPS

Here is this month's selection of Traders' Tips, contributed by various developers of technical analysis software to help readers more easily implement some of the strategies presented in this and other issues.

You can copy these formulas and programs for easy use in your spreadsheet or analysis software. Simply "select" the desired text by highlighting as you would in any word processing program, then use your standard key command for copy or choose "copy" from the browser menu. The copied text can then be "pasted" into any open spreadsheet or other software by selecting an insertion point and executing a paste command. By toggling back and forth between an application window and the open Web page, data can be transferred with ease.

This month's tips include formulas and programs for:

TRADESTATION: CORONA CHARTS
WEALTH-LAB: CORONA CHARTS
eSIGNAL: CORONA CHARTS
AMIBROKER: CORONA CHARTS
NEUROSHELL TRADER: CORONA CHARTS
WORDEN BROTHERS BLOCKS: THE MIDAS TOUCH
AIQ: MOCS EXIT INDICATOR
TRADERSTUDIO: CORONA CHARTS
TRADE IDEAS: FADING THE MARKET
VT TRADER: GUPPY MULTIPLE MOVING AVERAGE (GMMA)

or return to November 2008 Contents


TRADESTATION: CORONA CHARTS

John Ehlers's corona indicators, as described in his article in this issue, "Corona Charts," provide a "multidimensional" view of market activity. See Figure 1 for a sample implementation.
EasyLanguage code for the studies was already provided by Ehlers for the article. To download this EasyLanguage code, go to the TradeStation and EasyLanguage Support Forum (https://www.tradestation.com/Discussions/forum.aspx?Forum_ID=213) and search for the file "CoronaCharts.Eld."

FIGURE 1: TRADESTATION, CORONA CHARTS AND ITS INDICATORS. Ehlers's corona indicators shown here are: cycle period, swing position, signal to noise ratio, and trend vigor. The left pane displays a 15-minute chart of the forex symbol EUR/USD. The right pane displays a 400-tick chart of the continuous 30-year bond futures contract.
This article is for informational purposes. No type of trading or investment recommendation, advice or strategy is being made, given or in any manner provided by TradeStation Securities or its affiliates.
--Mark Mills
TradeStation Securities, Inc.
A subsidiary of TradeStation Group, Inc.
www.TradeStation.com
GO BACK

WEALTH-LAB: CORONA CHARTS

Even if you don't use corona charts for trading, you still might be able to impress someone with these colorful charts -- my spouse certainly was! We wrapped the indicator creation and plotting in a tidy SuperIndicators method so that all four indicators can be returned to a Strategy script in a single call. The full translation for Wealth-Lab 5 (.NET) WealthScript can be found in the STOCKS & COMMODITIES Traders' Tips section at the Wealth-Lab.com wiki site. A sample chart is shown in Figure 2.

FIGURE 2: WEALTH-LAB, CORONA CHART. The trend vigor's ominous corona in June 2008 provided a good warning that MSFT's March--April rally had lost its steam.
WealthScript code (C#):

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

namespace WealthLab.Strategies
{
   public class CoronaCharts : WealthScript
   {
      public const double twoPi = 2 * Math.PI;
      public const double fourPi = 4 * Math.PI;
      
      public class ArrayHolder
      {   // current, old, older
         internal double I, I2, I3;  
         internal double Q, Q2, Q3;
         internal double R, R2, R3;
         internal double Im, Im2, Im3; 
         internal double A; 
         internal double dB, dB2;  
      }
      
      // Keep cntMax fifo samples and find the Highest and Lowest lead for samples in the list
      
private void PhaseList(ref ArrayList fifo, int cntMax, double lead, out double H, out double L)
      {
         H = lead; L = lead;
         if( fifo.Count < cntMax ) 
            fifo.Add(lead);
         else {
            fifo.RemoveAt(0);
            fifo.Add(lead);
         }
         for (int n = 0; n < fifo.Count - 1; n++) {
            double val = (double)fifo[n];
            if( val > H ) H = val;
            if( val < L ) L = val;
         }
      }
      
      public void SuperIndicators(DataSeries ds, out DataSeries domCycMdn,
         out DataSeries snrSer, out DataSeries psnSer, out DataSeries tvSer)
      
       {         
         // Initialize arrays
         ArrayHolder[] ah = new ArrayHolder[61];   
         for( int n = 12; n < 61; n++ )
            ah[n] = new ArrayHolder();
         
         double domCycle = 0d;
         string s = ds.Description + ")";         
         DataSeries[] DB = new DataSeries[61];  
         DataSeries domCyc = Close - Close;   
         domCycMdn = domCyc * 0d;
         snrSer = domCycMdn + 0d;  
         psnSer = snrSer + 0d;  
         tvSer = psnSer + 0d;
         
         domCyc.Description = "DC(" + s;
         domCycMdn.Description = "DomCyc(" + s;   
         snrSer.Description = "SNR(" + s;         
         psnSer.Description = "Swing Position(" + s;
         tvSer.Description = "Trend Vigor(" + s;
         
         // Create and plot the decibel series - change the colors later   
         ChartPane dbPane = CreatePane(40, false, false );
         for( int n = 12; n < 61; n++ ) {
            double d = n / 2.0;            
            DB[n] = domCyc + d;            
            DB[n].Description = "Cycle." + d.ToString();   
            PlotSeries(dbPane, DB[n], Color.Black, LineStyle.Solid, 4);
         }
         
         DataSeries[] Raster = new DataSeries[51];   // SNR Corona chart
         ChartPane snrPane = CreatePane(40, false, false );
         for( int n = 1; n < 51; n++ ) {
            double d = 1d + n / 5.0;
            Raster[n] = domCyc + d;
            Raster[n].Description = "SNR." + d.ToString();   
            PlotSeries(snrPane, Raster[n], Color.Black, LineStyle.Solid, 4);
         }
         
         DataSeries[] RasterSwg = new DataSeries[51];   // Swing Corona chart
         ChartPane swgPane = CreatePane(40, false, false );
         for( int n = 1; n < 51; n++ ) {
            double d = 0.2 * n - 5.0;
            RasterSwg[n] = domCyc + d;
            RasterSwg[n].Description = "Swing." + d.ToString();   
            PlotSeries(swgPane, RasterSwg[n], Color.Black, LineStyle.Solid, 4);
         }
         
         DataSeries[] RasterTV = new DataSeries[51];   // Trend Vigor Corona chart
         ChartPane tvPane = CreatePane(40, false, false );
         for( int n = 1; n < 51; n++ ) {
            double d = 0.4 * n - 10.0;
            RasterTV[n] = domCyc + d;
            RasterTV[n].Description = "TV." + d.ToString();   
            PlotSeries(tvPane, RasterTV[n], Color.Black, LineStyle.Solid, 4);
         }
                     
         Color[] color = new Color[21];      // Convert decibels to RGB color for display
         for( int n = 0; n <= 10; n++ )      // yellow to red: 0 to 10 dB
            color[n] = Color.FromArgb(255, (int)(255 - (255 * n / 10)), 0);
         for( int n = 11; n <= 20; n++ )      // red to black: 11 to 20 db
            color[n] = Color.FromArgb( (int)(255 * (20 - n)/10 ), 0, 0);
         
         Color[] colorSNR = new Color[21];   // Corona chart SNR colors
         for( int n = 0; n <= 10; n++ ) {
            int c1 = 220 - ( 22 * n );
            int c2 = 255 - ( 7 * n );  
            colorSNR[n] = Color.FromArgb(c1, c2, c2);
         }            
         for( int n = 11; n <= 20; n++ ) {
            int c2 = (int)(190 * ( 2 - n/10d ));  
            colorSNR[n] = Color.FromArgb(0, c2, c2);
         }   
                  
         Color[] colorSwg = new Color[21];   // Corona chart Swing colors
         for( int n = 0; n <= 10; n++ ) {
            int c1 = 180 - ( 18 * n );
            int c2 = 255 - ( 8 * n );  
            int c3 = 210 - ( 15 * n );  
            colorSwg[n] = Color.FromArgb(c1, c2, c3);
         }
         for( int n = 11; n <= 20; n++ ) {
            int c2 = (int)(172 * ( 2 - n/10d )); 
            int c3 = (int)(64 * ( 2 - n/10d ));  
            colorSwg[n] = Color.FromArgb(0, c2, c3);
         }

         Color[] colorTV = new Color[21];   // Trend Vigor chart colors
         for( int n = 0; n <= 10; n++ ) {
            int c1 = 60 - ( 6 * n );
            int c2 = 120 - ( 12 * n );  
            colorTV[n] = Color.FromArgb(c1, c2, 255);
         }
         for( int n = 11; n <= 20; n++ )
            colorTV[n] = Color.FromArgb(0, 0, (int)(255 * ( 2 - n/10d )));
         
         // Detrend data by High Pass Filtering with a 40 Period cutoff      
         DataSeries HP = domCyc;            
         double alpha = (1 - Math.Sin(twoPi/30)) / Math.Cos(twoPi/30); 
         for(int bar = 1; bar < Bars.Count; bar++)
            HP[bar] = 0.5 * (1 + alpha)* Momentum.Series(ds, 1)[bar] + alpha * HP[bar-1];
         DataSeries smoothHP = FIR.Series(HP, "1,2,3,3,2,1");
         DataSeries hmlSer = Median.Series( High - Low, 5 );
         
         double avg, signal, noise, snr;   // Variables SNR       
         double avg1 = 0d;
         double signal1 = 0d;
         double noise1 = 0d;
                  
         const double delta2 = 0.1;      // Variables Swing, TV
         double BP2_1 = 0d;
         double BP2_2 = 0d;
         double beta2, BP2, g2, alpha2, Q2, Lead60, HL, LL, widthSwg;
         ArrayList fifoList = new ArrayList(51);
         ArrayList fifoPsn = new ArrayList(21);
         double ratio = 0d;
         double ratio1 = 0d;
         double widthTV = 0d;
         
         // arrays to hold raster values from previous bar
         int[] raster2 = new int[51];
         int[] raster2Swg = new int[51];
         int[] raster2TV = new int[51];
         
         for( int bar = 12; bar < Bars.Count; bar++ )
         {
            double maxAmpl = 0d;
            double delta = -0.015 * bar + 0.5;
            delta = delta < 0.1 - 0.1 : delta;
            for( int n = 12; n < 61; n++ )
            {
               double beta = Math.Cos(fourPi / n);               
               double g = 1 / Math.Cos(2 * fourPi * delta / n);   
               double a = g - Math.Sqrt(g * g - 1);
               ah[n].Q = Momentum.Series(smoothHP, 1)[bar] * n / fourPi; 
               ah[n].I = smoothHP[bar];
               ah[n].R = 0.5 * (1 - a) * (ah[n].I - ah[n].I3) + beta * (1 + a) * ah[n].R2 - a * ah[n].R3;
               ah[n].Im = 0.5 * (1 - a) * (ah[n].Q - ah[n].Q3) + beta * (1 + a) * ah[n].Im2 - a * ah[n].Im3;
               ah[n].A = ah[n].R * ah[n].R + ah[n].Im * ah[n].Im;
               maxAmpl = ah[n].A > maxAmpl - ah[n].A : maxAmpl;
            }
            
            double num = 0;   double den = 0;
            for( int n = 12; n < 61; n++ )
            {
               ah[n].I3 = ah[n].I2;
               ah[n].I2 = ah[n].I;
               ah[n].Q3 = ah[n].Q2;
               ah[n].Q2 = ah[n].Q;
               ah[n].R3 = ah[n].R2;
               ah[n].R2 = ah[n].R;
               ah[n].Im3 = ah[n].Im2;
               ah[n].Im2 = ah[n].Im;
               ah[n].dB2 = ah[n].dB;              
               
               if( maxAmpl != 0 && ah[n].A / maxAmpl > 0 )
                  ah[n].dB = 10 * Math.Log10( (1 - 0.99 * ah[n].A / maxAmpl) / 0.01 );
               ah[n].dB = 0.33 * ah[n].dB + 0.67 * ah[n].dB2;      
               ah[n].dB = ah[n].dB > 20 - 20 : ah[n].dB;
               SetSeriesBarColor(bar, DB[n], color[(int)Math.Round(ah[n].dB)]);
               
               if( ah[n].dB <= 6 ) {            
                  num += n * (20 - ah[n].dB);
                  den += (20 - ah[n].dB);
               }               
               if( den != 0 ) domCycle = 0.5 * num / den;  
            }
            domCycMdn[bar] = Median.Value(bar, domCyc, 5);
            domCycMdn[bar] = domCycle < 6 - 6: domCycle;   
            
            // Calculate SNR this bar
            signal = 0d;
            noise = 0d;
            snr = 0d;
            avg = 0.1 * ds[bar] + 0.9 * avg1;
            if( avg != 0d || maxAmpl > 0 )
               signal = 0.2 * Math.Sqrt(maxAmpl) + 0.9 * signal1;
            if( avg != 0d )
               noise = 0.1 * hmlSer[bar] + 0.9 * noise1;
            if( signal != 0d || noise != 0d )
               snr = 20 * Math.Log10(signal/noise) + 3.5;
            snr = snr < 1d - 0d : snr;
            snr = snr > 10d - 10d : snr;
            snr = snr * 0.1;   
            snrSer[bar] = snr * 10 + 1;
            double Width = snr > 0.5 - 0d : -0.4 * snr + 0.2;
            
            // Calculate the Swing this bar
            beta2 = Math.Cos(twoPi / domCycMdn[bar]);
            g2 = 1 / Math.Cos(fourPi * delta2 / domCycMdn[bar]);
            alpha2 = g2 - Math.Sqrt(g2 * g2 - 1);
            BP2 = 0.5 * (1 - alpha2) * (ds[bar] - ds[bar-2]) 
               + beta2 * (1 + alpha2) * BP2_1 - alpha2 * BP2_2;
            //Quadrature component is derivative of InPhase component divided by omega
            Q2 = (domCycMdn[bar] / twoPi) * (BP2 - BP2_1);
            Lead60 = 0.5 * BP2 + 0.866 * Q2;
            PhaseList(ref fifoList, 50, Lead60, out HL, out LL);
            double Psn = (Lead60 - LL) / (HL - LL);
            PhaseList(ref fifoPsn, 20, Psn, out HL, out LL); 
            if( HL - LL > 0.85 ) widthSwg = 0.01;
            else widthSwg = 0.15 * (HL - LL);
            psnSer[bar] = 10 * Psn - 5d;
            
            // Calculate Trend Vigor this bar
            // (Filter Bandpass component - same as Swing above; substitute variable names)
            
            //Pythagorean theorem to establish cycle amplitude
            double Ampl2 = Math.Sqrt(BP2 * BP2 + Q2 * Q2);
            
            //Trend amplitude taken over the cycle period
            int cycPeriod = (int)(domCycMdn[bar] - 1);
            if( cycPeriod < 12 ) cycPeriod = 12;
            double Trend = ds[bar] - ds[cycPeriod];
            if( Trend != 0 && Ampl2 != 0 ) 
               ratio = 0.33 * Trend /Ampl2 + 0.67 * ratio1;
            if( ratio > 10 ) ratio = 10d;
            if( ratio < -10 ) ratio = -10d;
            
            double tv = 0.05 * (ratio + 10d);
            if( tv < 0.3 || tv > 0.7 ) widthTV = 0.01;
            if( tv >= 0.3 && tv < 0.5 ) widthTV = tv - 0.3;
            if( tv >= 0.5 && tv <= 0.7 ) widthTV = 0.7 - tv;
            tvSer[bar] = 20d * tv - 10d;
            
            /* Plot the rasters... */
            int snr50 = (int)Math.Round(50 * snr);
            int psn50 = (int)Math.Round(50 * Psn);
            int tv50  = (int)Math.Round(50 * tv);
            
            for( int n = 1; n < 51; n++ )
            {   // 0.4 used below comes from 20/50 to normalize the color from 1 to 20
               double raster = 20d;               
               if( n < snr50 )  // bottom of corona
                  raster = 0.5 * (Math.Pow((20 * snr - 0.4 * n) / Width, 0.8) + raster2[n]);
               else if( n > snr50 && (0.4 * n - 20 * snr) / Width > 1 )  // top of corona
                  raster = 0.5 * (Math.Pow((-20 * snr + 0.4 * n) / Width, 0.8) + raster2[n]);
               else if( n == snr50 )
                  raster = 0.5 * raster2[n];
               if ( raster > 20 ) raster = 20;
               else if ( raster < 0 ) raster = 0;
               if ( snr > 0.5 ) raster = 20;
               SetSeriesBarColor(bar, Raster[n], colorSNR[(int)(raster)]);
               raster2[n] = (int)raster;
               
               // Plot the Swing raster
               double rasterSwg = 20d;
               if( n < psn50 )  // bottom of corona
                  rasterSwg = 0.5 * (Math.Pow((20 * Psn - 0.4 * n) / widthSwg, 0.95) + 0.5 * raster2Swg[n]);
               else if( n > psn50 && (0.4 * n - 20 * Psn) / widthSwg > 1 )  // top of corona
                  rasterSwg = 0.5 * (Math.Pow((-20 * Psn + 0.4 * n) / widthSwg, 0.95) + 0.5 * raster2Swg[n]);
               else if( n == psn50 )
                  rasterSwg = 0.5 * raster2Swg[n];
               if ( rasterSwg > 20 ) rasterSwg = 20;
               else if ( rasterSwg < 0 ) rasterSwg = 0;
               if ( HL - LL > 0.8 ) rasterSwg = 20;
               SetSeriesBarColor(bar, RasterSwg[n], colorSwg[(int)(rasterSwg)]);
               raster2Swg[n] = (int)rasterSwg;

               // Plot the Trend Vigor raster
               double rasterTV = 20d;
               if( n < tv50 ) 
                  rasterTV = 0.8 * (Math.Pow((20 * tv - 0.4 * n) / widthTV, 0.85) + 0.2 * raster2TV[n]);
               else if( n > tv50 )  // top of corona
                  rasterTV = 0.8 * (Math.Pow((-20 * tv + 0.4 * n) / widthTV, 0.85) + 0.2 * raster2TV[n]);
               else if( n == tv50 )
                  rasterTV = 0.5 * raster2TV[n];
               if( rasterTV < 0 ) rasterTV = 0;
               if( rasterTV > 20 || tv < 0.3 || tv > 0.7 ) rasterTV = 20;
               SetSeriesBarColor(bar, RasterTV[n], colorTV[(int)(rasterTV)]);
               raster2TV[n] = (int)rasterTV;
            }
            avg1 = avg;
            signal1 = signal;
            noise1 = noise;   
            BP2_2 = BP2_1;
            BP2_1 = BP2;
            ratio1 = ratio;
         }
         HideVolume();
         HidePaneLines();
         PlotSeries(dbPane, domCycMdn, Color.Yellow, WealthLab.LineStyle.Solid, 2);   
         DrawLabel(dbPane, "Dominant Cycle|", Color.Black);
         PlotSeries(snrPane, snrSer, Color.FromArgb(220, 255, 255), LineStyle.Solid, 2);
         DrawLabel(snrPane, "SNR|", Color.Black);
         PlotSeries(swgPane, psnSer, Color.FromArgb(180, 255, 210), LineStyle.Solid, 2);
         DrawLabel(swgPane, "Swing Position|", Color.Black);
         PlotSeries(tvPane, tvSer, Color.FromArgb(64, 128, 255), LineStyle.Solid, 2);
         DrawLabel(tvPane, "Trend Vigor|", Color.Black);
      }
      
      protected override void Execute()
      {
         // Declare the DataSeries to pass to the method
         DataSeries dc, snr, swing, tv;
         
         // Get the dominant cycle, SNR, Swing Position, and Trend Vigor for use in a strategy
         SuperIndicators(AveragePrice.Series(Bars), out dc, out snr, out swing, out tv);
      }
   }
}
-- Robert Sucher
www.wealth-lab.com
GO BACK

eSIGNAL: CORONA CHARTS

For this month's Traders' Tip, we've provided the following eSignal formulas

based on the formula code from John Ehlers's article in this issue, "Corona Charts." Figures 3 and 4 show sample implementations of the various corona charting indicators. To discuss this study or download a complete copy of the eSignal formula code, please visit the EFS Library Discussion Board forum under the Forums link at www.esignalcentral.com or visit our EFS KnowledgeBase at www.esignalcentral.com/support/kb/efs/. The eSignal formula scripts (EFS) are also available for copying and pasting from the Stocks & Commodities website at Traders.com.

FIGURE 3: eSIGNAL, CORONA CHART. This sample eSignal corona chart shows the cycle period and signal-to-noise-ratio indicators.

FIGURE 4: eSIGNAL, CORONA CHART. This sample eSignal corona chart shows the swing position and trend vigor indicators.
eSignal code
Corona Chart Trend Vigor EFS code:


/*********************************
Provided By:  
    eSignal (Copyright c eSignal), a division of Interactive Data 
    Corporation. 2008. All rights reserved. This sample eSignal 
    Formula Script (EFS) is for educational purposes only and may be 
    modified and saved under a new file name.  eSignal is not responsible
    for the functionality once modified.  eSignal reserves the right 
    to modify and overwrite this EFS file with each new release.
   

Description:        
    Corona Chart Trend Vigor    

Version:            1.0  9/10/2008

Notes:
    Once the dominant cycle period is known, the
    instantaneous trend is just the momentum across the full
    cycle period. This measurement is invariant with the
    position within the cycle. The trend slope is the same
    whether measured from cycle peak to cycle peak or cycle
    valley to cycle valley. The trend slope is normalized to the
    amplitude of the dominant cycle. A value of +2 means the
    trend slope is twice the dominant cycle amplitude, and
    therefore cautions you not to trade against the upslope.
    Similarly, a value of -2 means the trend slope is down and
    therefore cautions you not to buy against the downslope.
    The related article is copyrighted material. If you are not
    a subscriber of Stocks & Commodities, please visit www.traders.com.




Formula Parameters:                     Default:
    View Line Trend Vigor                 True
**********************************/

var fpArray = new Array();
var bInit = false;
var bVersion = null;


function preMain() {

    setPriceStudy(false);
    setShowCursorLabel(false);
    setShowTitleParameters( false );
    setStudyTitle("Corona Chart Trend Vigor");

    
var x=0;

    fpArray[x] = new FunctionParameter("ViewLine", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("View Line Trend Vigor");
        setDefault(true);
    }    
}



var     nLineR = 64;
var     nLineG = 128;
var     nLineB = 255;
var     nFuzzR = 0;
var     nFuzzG = 0;
var     nFuzzB = 255;
var     xPrice = null;


var     nRef_Global = 0;
var     ndelta = 0.1;
var     ngamma = 0;
var     nalpha = 0;
var     nbeta = 0;
var     nN = 0;
var     nPeriod = 0;
var     nMaxAmpl = 0;
var     nNum = 0;
var     nDenom = 0;
var     nDC = 0;
var     nDomCyc = 0;
var     nColor1 = 0;
var     nColor2 = 0;
var     nColor3 = 0;
var     nalpha1 = 0;
var     xHP = null;
var     nSmoothHP = 0;
var     nSmoothHP1 = 0;
var     ndelta1 = 0.1;
var     ngamma1 = 0;
var     nalpha2 = 0;
var     nbeta1 = 0;
var     nIP2 = 0;
var     nIP1 = 0;
var     nIP = 0;
var     nQ1 = 0;
var     nAmpl2 = 0;
var     nTrend = 0;
var     nRatio = 0;
var     nRatio1 = 0;
var     nTV = 0;
var     nWidth = 0;


var     xResultArray = new Array(52);

var     aI = new Array(60);
var     aOldI = new Array(60);
var     aOlderI = new Array(60);
var     aQ = new Array(60);
var     aOldQ = new Array(60);
var     aOlderQ = new Array(60);
var     aReal = new Array(60);
var     aOldReal = new Array(60);
var     aOlderReal = new Array(60);
var     aImag = new Array(60);
var     aOldImag = new Array(60);
var     aOlderImag = new Array(60);
var     aAmpl = new Array(60);
var     aOldAmpl = new Array(60);
var     aDB = new Array(60);
var     aOldDB = new Array(60);
var     aDC = new Array(60);
var     aRaster = new Array(50);
var     aOldRaster = new Array(50);




function main(ViewLine) {
var nResCounter = 0;
var nState = getBarState();
var pi = 3.1415926;

    
    
    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;   

    
    if (nState == BARSTATE_ALLBARS) {
        resetGlobalVars();    
    }
    
                  nalpha1 = (1 - (Math.sin(pi * (360 / 30) / 180)) / (Math.cos(pi * (360 / 30) / 180)));


    if (nState == BARSTATE_NEWBAR) {
        nSmoothHP1 = nSmoothHP;
    }

     
    if ( bInit == false ) {
        bShowDC  = ViewLine;
        xPrice = hl2();
        xHP = efsInternal("Calc_HP";, xPrice, nalpha1);
        bInit = true; 
        drawTextPixel( 10, 10,"Corona Chart Trend Vigor", Color.black, null,
                       Text.RELATIVETOLEFT | Text.RELATIVETOTOP, "Name" ,10, -10 );         
    } 

    if (getCurrentBarCount() < 7) return;


    
    if (nState == BARSTATE_NEWBAR) {
        aDC.pop();
        aDC.unshift(nDC);

        
        nRatio1 = nRatio;

        nIP2 = nIP1;
        nIP1 = nIP;

        
        for (nN = 12; nN <= 60; nN++) {
            aOlderI[nN] = aOldI[nN];
            aOldI[nN] = aI[nN];
            aOlderQ[nN] = aOldQ[nN];
            aOldQ[nN] = aQ[nN];
            aOlderReal[nN] = aOldReal[nN];
            aOldReal[nN] = aReal[nN];
            aOlderImag[nN] = aOldImag[nN];
            aOldImag[nN] = aImag[nN];
            aOldAmpl[nN] = aAmpl[nN];
            aOldDB[nN] = aDB[nN];
        }
        
        for (nN = 1; nN < 51; nN++) {
            aOldRaster[nN] = aRaster[nN];
        }
    }




            nSmoothHP = 0; 
    if (xPrice.getValue(-1) != null) nSmoothHP = 0;
    else nSmoothHP = xPrice.getValue(0) - xPrice.getValue(-1);
    
    if (xHP.getValue(-5) != null) {
        nSmoothHP = (xHP.getValue(0) + 2 * xHP.getValue(-1) + 3 * xHP.getValue(-2) + 
                     3 * xHP.getValue(-3) + 2 * xHP.getValue(-4) + xHP.getValue(-5)) / 12;
    }


        
   ndelta = (-0.015) * getCurrentBarCount() + 0.5;
        if (ndelta < 0.1) ndelta = 0.1;

        
        if (getCurrentBarCount() > 12) {
                for (nN = 12; nN <= 60; nN++) {
                        nbeta = Math.cos(pi * (720 / nN) / 180);
                        ngamma = 1 / Math.cos(pi * (1440 * ndelta / nN) / 180);
                        nalpha = ngamma -  Math.sqrt(ngamma * ngamma - 1);
                        aQ[nN] = (0.5 * nN / 6.28318) * (nSmoothHP - nSmoothHP1);
                        aI[nN] = nSmoothHP;
                        aReal[nN] = 0.5 * (1 - nalpha) * (aI[nN] - aOlderI[nN])
                                    + nbeta * (1 + nalpha) * aOldReal[nN] - nalpha * aOlderReal[nN];
                        aImag[nN] = 0.5 * (1 - nalpha) * (aQ[nN] - aOlderQ[nN])
                                    + nbeta * (1 + nalpha) * aOldImag[nN] - nalpha * aOlderImag[nN];
                        aAmpl[nN] = (aReal[nN] * aReal[nN] + aImag[nN] * aImag[nN]);
                }
        }


        
    nMaxAmpl = aAmpl[12];
         for (nN = 12; nN <= 60; nN++) {
 if (aAmpl[nN] > nMaxAmpl) nMaxAmpl = aAmpl[nN];
        }

     
        for (nN = 12; nN <= 60; nN++) {
                   if (nMaxAmpl != 0 && (aAmpl[nN] / nMaxAmpl) > 0) 
                    aDB[nN] = (-10) * Math.log(0.01 / (1 - 0.99 * aAmpl[nN] / nMaxAmpl)) / Math.log(10);
                aDB[nN] = 0.33 * aDB[nN] + 0.67 * aOldDB[nN];
                if (aDB[nN] > 20) aDB[nN] = 20;
        }

        nNum = 0;
        nDenom = 0;
        for (nN = 12; nN <= 60; nN++) {
                if (aDB[nN] <= 6) {
                        nNum = nNum + nN * (20 - aDB[nN]);
                        nDenom = nDenom + (20 - aDB[nN]);
                }
                if (nDenom != 0) {
            nDC = 0.5 * nNum / nDenom;
            aDC[0] = nDC;
        }
        }


        
   nDomCyc = Median(aDC, 5);


        if (nDomCyc < 6) nDomCyc = 6;

    
 nbeta1 = Math.cos(pi * (360 / nDomCyc) / 180);
    ngamma1 = 1 / Math.cos(pi * (720 * ndelta1 / nDomCyc) / 180);
    nalpha2 = ngamma1 - Math.sqrt(ngamma1 * ngamma1 - 1);
    nIP = 0.5 * (1 - nalpha2) * (xPrice.getValue(0) - xPrice.getValue(-2))
          + nbeta1 * (1 + nalpha2) * nIP1 - nalpha2 * nIP2;

    
    nQ1 = (nDomCyc / 6.28318) * (nIP - nIP1);

    nAmpl2 = Math.sqrt(nIP * nIP + nQ1 * nQ1);

    nTrend = xPrice.getValue(0) - xPrice.getValue(-nDomCyc + 1);
    if (nTrend != 0 && nAmpl2 != 0) nRatio = 0.33 * nTrend / nAmpl2 + 0.67 * nRatio1;
    if (nRatio > 10) nRatio = 10;
    if (nRatio < (-10)) nRatio = (-10);
    nTV = 0.05 * (nRatio + 10);
    if (nTV < 0.3 || nTV > 0.7) nWidth = 0.01;
    if (nTV >= 0.3 && nTV < 0.5) nWidth = nTV - 0.3;
    if (nTV > 0.5 && nTV <= 0.7) nWidth = -nTV + 0.7;


        
     for (nN = 1; nN < 51; nN++) {
        aRaster[nN] = 20;
                if (nN < Math.round(50 * nTV))
                    aRaster[nN] = 0.8 * (Math.pow((20 * nTV - 0.4 * nN) / nWidth, 0.85) + 0.2 * aOldRaster[nN]);
                if (nN > Math.round(50 * nTV))
                    aRaster[nN] = 0.8 * (Math.pow((-20 * nTV + 0.4 * nN) / nWidth, 0.85) + 0.2 * aOldRaster[nN]);
                if (nN == Math.round(50 * nTV)) aRaster[nN] = 0.5 * aOldRaster[nN];
                if (aRaster[nN] < 0) aRaster[nN] = 0;
                if (aRaster[nN] > 20 || nTV < 0.3 || nTV > 0.7) aRaster[nN] = 20;
        }



        
     for (nN = 1; nN < 51; nN++) {

                
           if (aRaster[nN] <= 10) {
                        nColor1 = Math.round(nLineR + aRaster[nN] * (nFuzzR - nLineR) / 10);
                        nColor2 = Math.round(nLineG + aRaster[nN] * (nFuzzG - nLineG) / 10);
                        nColor3 = Math.round(nLineB + aRaster[nN] * (nFuzzB - nLineB) / 10);
                }
                
           if (aRaster[nN] > 10) {
                        nColor1 = Math.round(nFuzzR * (2 - aRaster[nN] / 10));
                        nColor2 = Math.round(nFuzzG * (2 - aRaster[nN] / 10));
                        nColor3 = Math.round(nFuzzB * (2 - aRaster[nN] / 10));
                }


        
        xResultArray[nResCounter++] = 0.4 * nN - 10;
        setDefaultBarFgColor(Color.RGB(nColor1, nColor2, nColor3), nResCounter-1);
        setDefaultBarThickness(5, nResCounter - 1);
        }
        
    

    if (bShowDC == true) {
        xResultArray[nResCounter++] = (20 * nTV - 10);
        setBarFgColor(Color.RGB(nLineR, nLineG, nLineB), nResCounter-1);
        setBarThickness(3, nResCounter-1);
    }    

    
     return xResultArray; 
}


function resetGlobalVars(){
    nRef_Global = 0;
    ndelta = 0.1;
    ngamma = 0;
    nalpha = 0;
    nbeta = 0;
    nN = 0;
    nPeriod = 0;
    nMaxAmpl = 0;
    nNum = 0;
    nDenom = 0;
    nDC = 0;
    nDomCyc = 0;
    nColor1 = 0;
    nColor2 = 0;
    nColor3 = 0;
    nalpha1 = 0;
    
    nSmoothHP = 0;
    nSmoothHP1 = 0;
    ndelta1 = 0.1;
    ngamma1 = 0;
    nalpha2 = 0;
    nbeta1 = 0;
    nIP2 = 0;
    nIP1 = 0;
    nIP = 0;
    nQ1 = 0;
    nAmpl2 = 0;
    nTrend = 0;
    nRatio = 0;
    nRatio1 = 0;
    nTV = 0;
    nWidth = 0;

    
 for (var i = 0; i < 61; i++) {
        if (i <= 52) xResultArray[i] = null;
        aI[i] = 0;
        aOldI[i] = 0;
        aOlderI[i] = 0;
        aQ[i] = 0;
        aOldQ[i] = 0;
        aOlderQ[i] = 0;
        aReal[i] = 0;
        aOldReal[i] = 0;
        aOlderReal[i] = 0;
        aImag[i] = 0;
        aOldImag[i] = 0;
        aOlderImag[i] = 0;
        aAmpl[i] = 0;
        aOldAmpl[i] = 0;
        aDB[i] = 0;
        aOldDB[i] = 0;
        aDC[i] = 0;
    }
    
    for (var i = 1; i < 51; i++) {
        aRaster[i] = 0;
        aOldRaster[i] = 0;
    }   
}



// calcHP globals
var nPrevHP = null;
var nCurrHP = null;

function Calc_HP(x, nAlpha1) {
    var nHP = null;
    
    if (getCurrentBarCount() <= 5 ) {
        nCurrHP = x.getValue(0);
        return nCurrHP;
    } else {
        if (x.getValue(-1) == null) return null;
        if (getBarState() == BARSTATE_NEWBAR) nPrevHP = nCurrHP;
        nCurrHP = ( 0.5*(1 + nAlpha1)*(x.getValue(0) - x.getValue(-1)) + nAlpha1*nPrevHP );
        return nCurrHP;
    }

}


function Median(myArray, Length) {
    var aArray = new Array(Length);
    var nMedian = null;

    for (var i = 0; i < Length; i++) {
        aArray[i] = myArray[i];
    }

    
    aArray = aArray.sort(compareNumbers);
    nMedian = aArray[Math.round((Length-1)/2)];
    return nMedian;
}


function compareNumbers(a, b) {
   return a - b
}

function verify() {
    var b = false;
    if (getBuildNumber() < 779) {
        drawTextAbsolute(5, 35, "This study requires version 8.0 or later.", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "error");
        drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=https://www.esignal.com/download/default.asp", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "upgrade");
        return b;
    } else {
        b = true;
    }
    return b;
}

Corona Chart Swing Position EFS code:

/*********************************
Provided By:  
    eSignal (Copyright c eSignal), a division of Interactive Data 
    Corporation. 2008. All rights reserved. This sample eSignal 
    Formula Script (EFS) is for educational purposes only and may be 
    modified and saved under a new file name.  eSignal is not responsible
    for the functionality once modified.  eSignal reserves the right 
    to modify and overwrite this EFS file with each new release.
   

Description:        
    Corona Chart Swing Position

Version:            1.0  9/10/2008

Notes:
    The swing position indicator shows the phasing of
    the data within the dominant cycle. A value of -5 means the
    cycle is at its valley. A value of +5 means the cycle is at its
    peak. In a pure cycle the Swing Position will trace out the
    shape of a sine wave.
    The related article is copyrighted material. If you are not
    a subscriber of Stocks & Commodities, please visit www.traders.com.



Formula Parameters:                     Default:
    View Line                            True
**********************************/

var fpArray = new Array();
var bInit = false;
var bVersion = null;



function preMain() {

    setPriceStudy(false);
    setShowCursorLabel(false);
    setShowTitleParameters( false );
    setStudyTitle("Corona Chart Swing Position");
    setDefaultBarThickness(3, 50);

    
    var x=0;

    fpArray[x] = new FunctionParameter("ViewLine", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("View Line");
        setDefault(true);
    }    

}


var     nLineR = 180;
var     nLineG = 255;
var     nLineB = 210;
var     nFuzzR = 0;
var     nFuzzG = 172;
var     nFuzzB = 64;
var     xPrice = null;

var     nRef_Global = 0;
var     ndelta = 0.1;
var     ngamma = 0;
var     nalpha = 0;
var     nbeta = 0;
var     nN = 0;
var     nPeriod = 0;
var     nMaxAmpl = 0;
var     nNum = 0;
var     nDenom = 0;
var     nDC = 0;
var     nDomCyc = 0;
var     nColor1 = 0;
var     nColor2 = 0;
var     nColor3 = 0;
var     nalpha1 = 0;
var     xHP = null;
var     nSmoothHP = 0;
var     nSmoothHP1 = 0;
var     ngamma2 = 0;
var     nalpha2 = 0;
var     nbeta2 = 0;
var     ndelta2 = 0.1;
var     nBP2 = 0;
var     nBP2_1 = 0;
var     nBP2_2 = 0;
var     nQ2 = 0;
var     nHL = 0;
var     nLL = 0;
var     ncount = 0;
var     nWidth = 0;
var     nCalc_HP_Ref = 0;



var     xResultArray = new Array(51);

var     aI = new Array(61);
var     aOldI = new Array(61);
var     aOlderI = new Array(61);
var     aQ = new Array(61);
var     aOldQ = new Array(61);
var     aOlderQ = new Array(61);
var     aReal = new Array(61);
var     aOldReal = new Array(61);
var     aOlderReal = new Array(61);
var     aImag = new Array(61);
var     aOldImag = new Array(61);
var     aOlderImag = new Array(61);
var     aAmpl = new Array(61);
var     aOldAmpl = new Array(61);
var     aDB = new Array(61);
var     aOldDB = new Array(61);
var     aDC = new Array(61);
var     aPsn = new Array(61);


var     aRaster = new Array(51);
var     aOldRaster = new Array(51);
var     aLead60 = new Array(51);



function main(ViewLine) {
    var nResCounter = 0;
    var nState = getBarState();
    var pi = 3.1415926;
    var nCounter = 0;

    
    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;   


    if (nState == BARSTATE_ALLBARS) {
        resetVars();
    }
    
        nalpha1 = (1 - (Math.sin(pi * (360 / 30) / 180)) / (Math.cos(pi * (360 / 30) / 180)));

     
    if ( bInit == false ) {
        bShowDC  = ViewLine;
        xPrice = hl2();
        xHP = efsInternal("Calc_HP", xPrice, nalpha1);
        bInit = true; 
        drawTextPixel( 10, 10,"J Corona Chart Swing Position", Color.black, null,
                       Text.RELATIVETOLEFT | Text.RELATIVETOTOP, "Name" ,10, -10 );             
    } 
    
    if (getCurrentBarCount() < 5) return;



    
    if (nState == BARSTATE_NEWBAR) {
        nSmoothHP1 = nSmoothHP;
        
        aDC.pop();
        aDC.unshift(nDC);

        
        aLead60.pop();
        aLead60.unshift(0.5 * nBP2 + 0.866 * nQ2);

        aPsn.pop();
        aPsn.unshift((aLead60[0] - nLL) / (nHL - nLL));

        
        nBP2_2 = nBP2_1;
        nBP2_1 = nBP2;
        
        for (nN = 12; nN <= 60; nN++) {
            aOlderI[nN] = aOldI[nN];
            aOldI[nN] = aI[nN];
            aOlderQ[nN] = aOldQ[nN];
            aOldQ[nN] = aQ[nN];
            aOlderReal[nN] = aOldReal[nN];
            aOldReal[nN] = aReal[nN];
            aOlderImag[nN] = aOldImag[nN];
            aOldImag[nN] = aImag[nN];
            aOldAmpl[nN] = aAmpl[nN];
            aOldDB[nN] = aDB[nN];
        }
    }    

        
             nSmoothHP = 0 
    if (xPrice.getValue(-1) != null) nSmoothHP = xPrice.getValue(0) - xPrice.getValue(-1);
    
    if (xHP.getValue(-5) != null) {
        nSmoothHP = (xHP.getValue(0) + 2 * xHP.getValue(-1) + 3 * xHP.getValue(-2)
                     + 3 * xHP.getValue(-3) + 2 * xHP.getValue(-4) + xHP.getValue(-5)) / 12;
    }

              ndelta = (-0.015) * getCurrentBarCount() + 0.5;
                   if (ndelta < 0.1) ndelta = 0.1;


        
              if (getCurrentBarCount() > 12) {
                                 for (nN = 12; nN <= 60; nN++) {
                        nbeta = Math.cos(pi * (720 / nN) / 180);
                        ngamma = 1 / Math.cos(pi * (1440 * ndelta / nN) / 180);
                        nalpha = ngamma -  Math.sqrt(ngamma * ngamma - 1);
                        aQ[nN] = (0.5 * nN / 6.28318) * (nSmoothHP - nSmoothHP1);
                        aI[nN] = nSmoothHP;
                        aReal[nN] = 0.5 * (1 - nalpha) * (aI[nN] - aOlderI[nN])
                                    + nbeta * (1 + nalpha) * aOldReal[nN] - nalpha * aOlderReal[nN];
                        aImag[nN] = 0.5 * (1 - nalpha) * (aQ[nN] - aOlderQ[nN])
                                    + nbeta * (1 + nalpha) * aOldImag[nN] - nalpha * aOlderImag[nN];
                        aAmpl[nN] = (aReal[nN] * aReal[nN] + aImag[nN] * aImag[nN]);
                }
        }



        nMaxAmpl = aAmpl[12];
        for (nN = 12; nN <= 60; nN++) {
        if (aAmpl[nN] > nMaxAmpl) nMaxAmpl = aAmpl[nN];
        }

     
        
    for (nN = 12; nN <= 60; nN++) {
                if (nMaxAmpl != 0 && (aAmpl[nN] / nMaxAmpl) > 0) 
                    aDB[nN] = (-10) * Math.log(0.01 / (1 - 0.99 * aAmpl[nN] / nMaxAmpl)) / Math.log(10);
                aDB[nN] = 0.33 * aDB[nN] + 0.67 * aOldDB[nN];
                if (aDB[nN] > 20) aDB[nN] = 20;
        }

        
   nNum = 0;
        nDenom = 0;
        for (nN = 12; nN <= 60; nN++) {
                if (aDB[nN] <= 6) {
                        nNum = nNum + nN * (20 - aDB[nN]);
                        nDenom = nDenom + (20 - aDB[nN]);
                }
                if (nDenom != 0) {
            nDC = 0.5 * nNum / nDenom;
            aDC[0] = nDC;
        }
        }


        
   nDomCyc = Median(aDC, 5);
        if (nDomCyc < 6) nDomCyc = 6;


        
   nbeta2 = Math.cos(pi * (360 / nDomCyc) / 180);
        ngamma2 = 1 / Math.cos(pi * (720 * ndelta2 / nDomCyc) / 180);
        nalpha2 = ngamma2 - Math.sqrt(ngamma2 * ngamma2 - 1);

        nBP2 = 0.5 * (1 - nalpha2) * (xPrice.getValue(0) - xPrice.getValue(-1))
               + nbeta2 * (1 + nalpha2) * nBP2_1 - nalpha2 * nBP2_2;

    nQ2 = (nDomCyc / 6.28318)*(nBP2 - nBP2_1);

    aLead60[0] = 0.5 * nBP2 + 0.866 * nQ2;
        nHL = aLead60[0];
        nLL = aLead60[0];

        
    for (ncount = 0; ncount < 51; ncount++) {
                if (aLead60[ncount] > nHL) nHL =aLead60[ncount];
                if (aLead60[ncount] < nLL) nLL = aLead60[ncount];
        }


    aPsn[0] = (aLead60[0] - nLL) / (nHL - nLL);
        nHL = aPsn[0];
        nLL = aPsn[0];
    

        for (ncount = 0; ncount < 21; ncount++) {
                if (aPsn[ncount] > nHL)  nHL = aPsn[ncount];
                if (aPsn[ncount] < nLL)  nLL = aPsn[ncount];
        }


        
        if (nHL - nLL > 0.85) { nWidth = 0.01 } else  { nWidth = 0.15 * (nHL - nLL);}


        
for (nN = 1; nN < 51; nN++) {
                aRaster[nN] = 20;
                if (nN < Math.round(50 * aPsn[0])) 
                    aRaster[nN] = 0.5 * (Math.pow(((20 * aPsn[0] - 0.4 * nN) / nWidth), 0.95)
                    + 0.5 * aOldRaster[nN]);
                if (nN > Math.round(50 * aPsn[0])) 
                    aRaster[nN] = 0.5 * (Math.pow((((-20) * aPsn[0] + 0.4 * nN) / nWidth), 0.95)
                    + 0.5 * aOldRaster[nN]);
                if (nN == Math.round(50 * aPsn[0]))  aRaster[nN] = 0.5 * aOldRaster[nN];
                if (aRaster[nN] < 0)  aRaster[nN] = 0;
                if (aRaster[nN] > 20) aRaster[nN] = 20;
                if (nHL - nLL > 0.8) aRaster[nN] = 20;
                aOldRaster[nN] = aRaster[nN];
        }


        
for (nN = 1; nN < 51; nN++) {
                if (aRaster[nN] <= 10) {
                        nColor1 = Math.round(nLineR + aRaster[nN] * (nFuzzR - nLineR) / 10);
                        nColor2 = Math.round(nLineG + aRaster[nN] * (nFuzzG - nLineG) / 10);
                        nColor3 = Math.round(nLineB + aRaster[nN] * (nFuzzB - nLineB) / 10);
                }
                
        if (aRaster[nN] > 10) {
                        nColor1 = Math.round(nFuzzR * (2 - aRaster[nN] / 10));
                        nColor2 = Math.round(nFuzzG * (2 - aRaster[nN] / 10));
                        nColor3 = Math.round(nFuzzB * (2 - aRaster[nN] / 10));
                }

        
        xResultArray[nResCounter++] = 0.2 * nN - 5;
        setBarFgColor(Color.RGB(nColor1, nColor2, nColor3), nResCounter-1);
        setPlotType(PLOTTYPE_LINE, nResCounter-1); 
        setBarThickness(5, nResCounter-1);        
        }


    
     if (bShowDC == true) {
        xResultArray[nResCounter++] = (10 * aPsn[0] - 5);
        setBarFgColor(Color.RGB(nLineR, nLineG, nLineB), nResCounter-1);
    }    


    
    return xResultArray; 
}

function resetVars() {
    nRef_Global = 0;
    ndelta = 0.1;
    ngamma = 0;
    nalpha = 0;
    nbeta = 0;
    nN = 0;
    nPeriod = 0;
    nMaxAmpl = 0;
    nNum = 0;
    nDenom = 0;
    nDC = 0;
    nDomCyc = 0;
    nColor1 = 0;
    nColor2 = 0;
    nColor3 = 0;
    nalpha1 = 0;
    
    nSmoothHP = 0;
    nSmoothHP1 = 0;
    ngamma2 = 0;
    nalpha2 = 0;
    nbeta2 = 0;
    ndelta2 = 0.1;
    nBP2 = 0;
    nBP2_1 = 0;
    nBP2_2 = 0;
    nQ2 = 0;
    nHL = 0;
    nLL = 0;
    ncount = 0;
    nWidth = 0;
    nCalc_HP_Ref = 0;


    
for (var i = 0; i < 61; i++) {
        if (i < 51) xResultArray[i] = null;
        aI[i] = 0;
        aOldI[i] = 0;
        aOlderI[i] = 0;
        aQ[i] = 0;
        aOldQ[i] = 0;
        aOlderQ[i] = 0;
        aReal[i] = 0;
        aOldReal[i] = 0;
        aOlderReal[i] = 0;
        aImag[i] = 0;
        aOldImag[i] = 0;
        aOlderImag[i] = 0;
        aAmpl[i] = 0;
        aOldAmpl[i] = 0;
        aDB[i] = 0;
        aOldDB[i] = 0;
        aDC[i] = 0;
        aPsn[i] = 0;
    }
    
    for (var i = 0; i < 51; i++) {
        aRaster[i] = 0;
        aOldRaster[i] = 0;
        aLead60[i] = 0;
    }   

    
return;
}


// calcHP globals
var nPrevHP = null;
var nCurrHP = null;


function Calc_HP(x, nAlpha1) {
    var nHP = null;
    
    if (getCurrentBarCount() <= 5 ) {
        nCurrHP = x.getValue(0);
        return nCurrHP;
    } else {
        if (x.getValue(-1) == null) return null;
        if (getBarState() == BARSTATE_NEWBAR) nPrevHP = nCurrHP;
        nCurrHP = ( 0.5*(1 + nAlpha1)*(x.getValue(0) - x.getValue(-1)) + nAlpha1*nPrevHP );
        return nCurrHP;
    }

}



function Median(myArray, Length) {
    var aArray = new Array(Length);
    var nMedian = null;

    
    for (var i = 0; i < Length; i++) {
        aArray[i] = myArray[i];
    }

    aArray = aArray.sort(compareNumbers);
    nMedian = aArray[Math.round((Length-1)/2)];
    return nMedian;
}


function compareNumbers(a, b) {
   return a - b
}

function verify() {
    var b = false;
    if (getBuildNumber() < 779) {
        drawTextAbsolute(5, 35, "This study requires version 8.0 or later.", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "error");
        drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=https://www.esignal.com/download/default.asp", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "upgrade");
        return b;
    } else {
        b = true;
    }
    return b;
}

Corona Chart Signal To Noise EFS code:

/*********************************
Provided By:  
    eSignal (Copyright © eSignal), a division of Interactive Data 
    Corporation. 2008. All rights reserved. This sample eSignal 
    Formula Script (EFS) is for educational purposes only and may be 
    modified and saved under a new file name.  eSignal is not responsible
    for the functionality once modified.  eSignal reserves the right 
    to modify and overwrite this EFS file with each new release.
   

Description:        
    Corona Chart Signal To Noise Ratio


Version:            1.0  9/10/2008

Notes:
    The amplitude of the dominant cycle is normalized
    to the amplitude of the noise. Noise is defined as the
    average daily trading range. The Signal to Noise Ratio is
    measured in decibels (dB). Unless the cycle amplitude is at
    least 3 dB greater than the noise, the use of cycle-based
    entries and oscillators should be avoided because the
    uncertainty of getting a good entry and exit point during day
    can negate any potential profit realized from the cyclic
    swing. A Signal to Noise ratio in excess of 6 dB signals a
    strong cyclic component relative to the noise.  
    The related article is copyrighted material. If you are not
    a subscriber of Stocks & Commodities, please visit www.traders.com.




Formula Parameters:                     Default:
    View Line Signal To Noise Ratio      True
**********************************/




var fpArray = new Array();
var bInit = false;
var bVersion = null;

function preMain() {

    setPriceStudy(false);
    setShowCursorLabel(false);
    setShowTitleParameters( false );
    setStudyTitle("Corona Chart Signal To Noise Ratio");

    var x=0;

    fpArray[x] = new FunctionParameter("ViewLine", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("View Line Signal To Noise Ratio");
        setDefault(true);
    }    
    

}


var xResultArray = new Array(50);

var     nLineR = 220;
var     nLineG = 255;
var     nLineB = 255;
var     nFuzzR = 0;
var     nFuzzG = 190;
var     nFuzzB = 190;
var     xPrice = null;


var     nRef_Global = 0;
var     ndelta = 0.1;
var     ngamma = 0;
var     nalpha = 0;
var     nbeta = 0;
var     nN = 0;
var     nPeriod = 0;
var     nMaxAmpl = 0;
var     nNum = 0;
var     nDenom = 0;
var     nDC = 0;
var     nDomCyc = 0;
var     nColor1 = 0;
var     nColor2 = 0;
var     nColor3 = 0;
var     nalpha1 = 0;
var     xHP = null;
var     nSmoothHP = 0;
var     nSmoothHP1 = 0;
var     nAvg1 = 0;
var     nAvg = 0;
var     nSignal = 0;
var     nSignal1 = 0;
var     nNoise = 0;
var     nNoise1 = 0;
var     nSNR = 0;
var     nWidth = 0;



var     aI = new Array(60);
var     aOldI = new Array(60);
var     aOlderI = new Array(60);
var     aQ = new Array(60);
var     aOldQ = new Array(60);
var     aOlderQ = new Array(60);
var     aReal = new Array(60);
var     aOldReal = new Array(60);
var     aOlderReal = new Array(60);
var     aImag = new Array(60);
var     aOldImag = new Array(60);
var     aOlderImag = new Array(60);
var     aAmpl = new Array(60);
var     aOldAmpl = new Array(60);
var     aDB = new Array(60);
var     aOldDB = new Array(60);
var     aDC = new Array(60);
var     aRaster = new Array(50);
var     aOldRaster = new Array(50);




function main(ViewLine) {
var nResCounter = 0;
var nState = getBarState();
var pi = 3.1415926;
var nCounter = 0;

    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;   
    
    if (nState == BARSTATE_ALLBARS) {
        resetVars();
    }
 
        nalpha1 = (1 - (Math.sin(pi * (360 / 30) / 180)) / (Math.cos(pi * (360 / 30) / 180)));


    if (nState == BARSTATE_NEWBAR) {
        nSmoothHP1 = nSmoothHP;
        nAvg1 = nAvg;
        nSignal1 = nSignal;
        nNoise1 = nNoise;
    }

     
    if ( bInit == false ) {
        bShowDC  = ViewLine;
        xPrice = hl2();
        xHP = efsInternal("Calc_HP", xPrice, nalpha1);
        bInit = true; 
        drawTextPixel( 10, 10,"Corona Chart Signal To Noise Ratio", Color.black, null,
                       Text.RELATIVETOLEFT | Text.RELATIVETOTOP, "Name" ,10, -10 );         
    } 

    if (getCurrentBarCount() < 10) return;


    if (nState == BARSTATE_NEWBAR) {
        aDC.pop();
        aDC.unshift(nDC);
        
        aDB.pop();
        aDB.unshift();

        for (nN = 12; nN <= 60; nN++) {
            aOlderI[nN] = aOldI[nN];
            aOldI[nN] = aI[nN];
            aOlderQ[nN] = aOldQ[nN];
            aOldQ[nN] = aQ[nN];
            aOlderReal[nN] = aOldReal[nN];
            aOldReal[nN] = aReal[nN];
            aOlderImag[nN] = aOldImag[nN];
            aOldImag[nN] = aImag[nN];
            aOldAmpl[nN] = aAmpl[nN];
            aOldDB[nN] = aDB[nN];
        }  

        for (nN = 1; nN < 51; nN++) {
            aOldRaster[nN] = aRaster[nN];
        }
    }


    nSmoothHP = 0; 
    if (xPrice.getValue(-1) != null) nSmoothHP = 0;
    else nSmoothHP = xPrice.getValue(0) - xPrice.getValue(-1);
    
    if (xHP.getValue(-5) != null) {
        nSmoothHP = (xHP.getValue(0) + 2 * xHP.getValue(-1) + 3 * xHP.getValue(-2)
                     + 3 * xHP.getValue(-3) + 2 * xHP.getValue(-4) + xHP.getValue(-5)) / 12;
    }

        ndelta = (-0.015) * getCurrentBarCount() + 0.5;
        if (ndelta < 0.1) ndelta = 0.1;

        
        if (getCurrentBarCount() > 12) {
                for (nN = 12; nN <= 60; nN++) {
                        nbeta = Math.cos(pi * (720 / nN) / 180);
                        ngamma = 1 / Math.cos(pi * (1440 * ndelta / nN) / 180);
                        nalpha = ngamma -  Math.sqrt(ngamma * ngamma - 1);
                        aQ[nN] = (0.5 * nN / 6.28318) * (nSmoothHP - nSmoothHP1);
                        aI[nN] = nSmoothHP;
                        aReal[nN] = 0.5 * (1 - nalpha) * (aI[nN] - aOlderI[nN])
                                    + nbeta * (1 + nalpha) * aOldReal[nN] - nalpha * aOlderReal[nN];
                        aImag[nN] = 0.5 * (1 - nalpha) * (aQ[nN] - aOlderQ[nN])
                                    + nbeta * (1 + nalpha) * aOldImag[nN] - nalpha * aOlderImag[nN];
                        aAmpl[nN] = (aReal[nN] * aReal[nN] + aImag[nN] * aImag[nN]);
                }
        }


    
        nMaxAmpl = aAmpl[12];
        for (nN = 12; nN <= 60; nN++) {
        if (aAmpl[nN] > nMaxAmpl) nMaxAmpl = aAmpl[nN];
        //aOldDB[nN] = aDB[nN];
        }

     
        for (nN = 12; nN <= 60; nN++) {
                if (nMaxAmpl != 0 && (aAmpl[nN] / nMaxAmpl) > 0) 
                    aDB[nN] = (-10) * Math.log(0.01 / (1 - 0.99 * aAmpl[nN] / nMaxAmpl)) / Math.log(10);
                aDB[nN] = 0.33 * aDB[nN] + 0.67 * aOldDB[nN];
                if (aDB[nN] > 20) aDB[nN] = 20;
        }

        nNum = 0;
        nDenom = 0;
        for (nN = 12; nN <= 60; nN++) {
                if (aDB[nN] <= 6) {
                        nNum = nNum + nN * (20 - aDB[nN]);
                        nDenom = nDenom + (20 - aDB[nN]);
                }
                if (nDenom != 0) {
            nDC = 0.5 * nNum / nDenom;
            aDC[0] = nDC;
        }
        }


        nDomCyc = Median(aDC, 5);

        if (nDomCyc < 6) nDomCyc = 6;

        nAvg = 0.1 * xPrice.getValue(0) + 0.9 * nAvg1;
        
    if (nAvg != 0 && nMaxAmpl > 0) nSignal = 0.2 * Math.sqrt(nMaxAmpl) + 0.9 * nSignal1;
        if (nAvg != 0 && getCurrentBarCount() > 5) nNoise = 0.1 * Median2(5) + 0.9 * nNoise1;
        if (nSignal != 0 && nNoise != 0) nSNR = 20 * Math.log(nSignal / nNoise) / Math.log(10) + 3.5;
        if (nSNR < 1) nSNR = 0;
        if (nSNR > 11) nSNR = 10;

        nSNR = 0.1 * nSNR;
        nWidth = (-0.4) * nSNR + 0.2;
        if (nSNR > 0.5) nWidth = 0;

        for (nN = 1; nN < 51; nN++) {
                aRaster[nN] = 20;
                if (nN < Math.round(50 * nSNR))
                    aRaster[nN] = 0.5 * (Math.pow((20 * nSNR - 0.4 * nN) / nWidth, 0.8) + aOldRaster[nN]);
                if (nN > Math.round(50 * nSNR) && (0.4 * nN - 20 * nSNR) / nWidth > 1)
                    aRaster[nN] = 0.5 * (Math.pow(((-20) * nSNR + 0.4 * nN)/ nWidth, 0.8) + aOldRaster[nN]) ;
                if (nN == Math.round(50 * nSNR)) aRaster[nN] = 0 + 0.5 * aOldRaster[nN];
                if (aRaster[nN] < 0) aRaster[nN] = 0;           
                if (aRaster[nN] > 20) aRaster[nN] = 20;
                if (nSNR > 0.5) aRaster[nN] = 20;
        }

        for (nN = 1; nN < 51; nN++) {
                if (aRaster[nN] <= 10) {
                        nColor1 = Math.round(nLineR + aRaster[nN] * (nFuzzR - nLineR) / 10);
                        nColor2 = Math.round(nLineG + aRaster[nN] * (nFuzzG - nLineG) / 10);
                        nColor3 = Math.round(nLineB + aRaster[nN] * (nFuzzB - nLineB) / 10);
                }
                
        if (aRaster[nN] > 10) {
                        nColor1 = Math.round(nFuzzR * (2 - aRaster[nN] / 10));
                        nColor2 = Math.round(nFuzzG * (2 - aRaster[nN] / 10));
                        nColor3 = Math.round(nFuzzB * (2 - aRaster[nN] / 10));
                }

        xResultArray[nResCounter++] = 0.2 * nN + 1;
        setBarFgColor(Color.RGB(nColor1, nColor2, nColor3), nResCounter-1);
        setPlotType(PLOTTYPE_LINE, nResCounter-1); 
        setBarThickness(5, nResCounter-1);

        }

    if (bShowDC == true) {
        xResultArray[nResCounter++] = 10 * nSNR + 1;
        setBarFgColor(Color.RGB(nLineR, nLineG, nLineB), nResCounter-1);
        setBarThickness(3, nResCounter-1);
    }

    return xResultArray; 
}


function resetVars(){   
    nRef_Global = 0;
    ndelta = 0.1;
    ngamma = 0;
    nalpha = 0;
    nbeta = 0;
    nN = 0;
    nPeriod = 0;
    nMaxAmpl = 0;
    nNum = 0;
    nDenom = 0;
    nDC = 0;
    nDomCyc = 0;
    nColor1 = 0;
    nColor2 = 0;
    nColor3 = 0;
    nalpha1 = 0;
    nSmoothHP = 0;
    nSmoothHP1 = 0;
    nAvg1 = 0;
    nAvg = 0;
    nSignal = 0;
    nSignal1 = 0;
    nNoise = 0;
    nNoise1 = 0;
    nSNR = 0;
    nWidth = 0;
        
    
    for (var i = 0; i < 61; i++) {
        if (i <= 50) xResultArray[i] = null;
        aI[i] = 0;
        aOldI[i] = 0;
        aOlderI[i] = 0;
        aQ[i] = 0;
        aOldQ[i] = 0;
        aOlderQ[i] = 0;
        aReal[i] = 0;
        aOldReal[i] = 0;
        aOlderReal[i] = 0;
        aImag[i] = 0;
        aOldImag[i] = 0;
        aOlderImag[i] = 0;
        aAmpl[i] = 0;
        aOldAmpl[i] = 0;
        aDB[i] = 0;
        aOldDB[i] = 0;
        aDC[i] = 0;
    }
    
    for (var i = 0; i < 51; i++) {
        aRaster[i] = 0;
        aOldRaster[i] = 0;
    }   
    
    return;
}

// calcHP globals
var nPrevHP = null;
var nCurrHP = null;

function Calc_HP(x, nAlpha1) {
    var nHP = null;
    
    if (getCurrentBarCount() <= 5 ) {
        nCurrHP = x.getValue(0);
        return nCurrHP;
    } else {
        if (x.getValue(-1) == null) return null;
        if (getBarState() == BARSTATE_NEWBAR) nPrevHP = nCurrHP;
        nCurrHP = ( 0.5*(1 + nAlpha1)*(x.getValue(0) - x.getValue(-1)) + nAlpha1*nPrevHP );
        return nCurrHP;
    }

}

function Median(myArray, Length) {
    var aArray = new Array(Length);
    var nMedian = null;

    for (var i = 0; i < Length; i++) {
        aArray[i] = myArray[i];
    }

    aArray = aArray.sort(compareNumbers);
    nMedian = aArray[Math.round((Length-1)/2)];
    return nMedian;
}

function Median2(Length) {
    var aArray = new Array(Length);
    var nMedian = null;

    for (var i = 0; i < Length; i++) {
        aArray[i] = high(-i) - low(-i);
    }

    aArray = aArray.sort(compareNumbers);
    nMedian = aArray[Math.round((Length-1)/2)];
    return nMedian;
}

function compareNumbers(a, b) {
   return a - b
}


function verify() {
    var b = false;
    if (getBuildNumber() < 779) {
        drawTextAbsolute(5, 35, "This study requires version 8.0 or later.", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "error");
        drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=https://www.esignal.com/download/default.asp", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "upgrade");
        return b;
    } else {
        b = true;
    }
    return b;
}










Corona Chart Cycle Period EFS code:


/*********************************
Provided By:  
    eSignal (Copyright c eSignal), a division of Interactive Data 
    Corporation. 2008. All rights reserved. This sample eSignal 
    Formula Script (EFS) is for educational purposes only and may be 
    modified and saved under a new file name.  eSignal is not responsible
    for the functionality once modified.  eSignal reserves the right 
    to modify and overwrite this EFS file with each new release.
   

Description:        
    Corona Chart Cycle Period    

Version:            1.0  9/10/2008

Notes:
    The spectral content of the data are measured in a
    bank of contiguous filters as described in “Measuring Cycle
    Periods” in the March 2008 issue of Stocks & Commodities
    Magazine. The filter having the strongest output is selected
    as the current dominant cycle period. The cycle period is
    measured as the number of bars contained in one full cycle
    period.
    The related article is copyrighted material. If you are not
    a subscriber of Stocks & Commodities, please visit www.traders.com.


Formula Parameters:                     Default:
    View Line DC                         True
**********************************/

var fpArray = new Array();
var bInit = false;
var bVersion = null;

function preMain() {

    setPriceStudy(false);
    setShowCursorLabel(false);
    setShowTitleParameters( false );
    setStudyTitle("Corona Chart Cycle Period");
    
    // Dominant Cycle properties
    setDefaultBarFgColor(Color.RGB(nLineR, nLineG, nLineB), 60);
    setDefaultBarThickness(3, 60);
  
    var x=0;

    fpArray[x] = new FunctionParameter("ViewLine", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("View Line DC");
        setDefault(true);
    }    
}


var     xResultArray = new Array(61);

var     nLineR = 255;
var     nLineG = 255;
var     nLineB = 0;
var     nFuzzR = 255;
var     nFuzzG = 0;
var     nFuzzB = 0;
var     bShowDC = true;
var     xPrice = null;


var     nRef_Global = 0;
var     ndelta = 0.1;
var     ngamma = 0;
var     nalpha = 0;
var     nbeta = 0;
var     nN = 0;
var     nPeriod = 0;
var     nMaxAmpl = 0;
var     nNum = 0;
var     nDenom = 0;
var     nDC = 0;
var     nDomCyc = 0;
var     nColor1 = 0;
var     nColor2 = 0;
var     nColor3 = 0;
var     nalpha1 = 0;
var     xHP = null;
var     nSmoothHP = 0;
var     nSmoothHP1 = 0;

var     aI = new Array(60);
var     aOldI = new Array(60);
var     aOlderI = new Array(60);
var     aQ = new Array(60);
var     aOldQ = new Array(60);
var     aOlderQ = new Array(60);
var     aReal = new Array(60);
var     aOldReal = new Array(60);
var     aOlderReal = new Array(60);
var     aImag = new Array(60);
var     aOldImag = new Array(60);
var     aOlderImag = new Array(60);
var     aAmpl = new Array(60);
var     aOldAmpl = new Array(60);
var     aDB = new Array(60);
var     aOldDB = new Array(60);
var     aDC = new Array(60);


function main(ViewLine) {
var nResCounter = 0;
var nState = getBarState();
var pi = 3.1415926;
var nCounter = 0;

    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;   

    if (nState == BARSTATE_ALLBARS) {
        resetVars();
    }

        nalpha1 = (1 - (Math.sin(pi * (360 / 30) / 180)) / (Math.cos(pi * (360 / 30) / 180)));

    
    if (nState == BARSTATE_NEWBAR) nSmoothHP1 = nSmoothHP;
    

    if ( bInit == false ) {
        bShowDC  = ViewLine;
        xPrice = hl2();
        xHP = efsInternal("Calc_HP", xPrice, nalpha1);
        bInit = true; 
        drawTextPixel( 10, 10,"Corona Chart Cycle Period", Color.black, null,
                       Text.RELATIVETOLEFT | Text.RELATIVETOTOP, "Name" ,10, -10 );         
    } 

    if (getCurrentBarCount() < 61) return;


    if (nState == BARSTATE_NEWBAR) {
        aDC.pop();
        aDC.unshift(nDC);

        for (nN = 12; nN <= 60; nN++) {
            aOlderI[nN] = aOldI[nN];
            aOldI[nN] = aI[nN];
            aOlderQ[nN] = aOldQ[nN];
            aOldQ[nN] = aQ[nN];
            aOlderReal[nN] = aOldReal[nN];
            aOldReal[nN] = aReal[nN];
            aOlderImag[nN] = aOldImag[nN];
            aOldImag[nN] = aImag[nN];
            aOldAmpl[nN] = aAmpl[nN];
            aOldDB[nN] = aDB[nN];
        }
    }


        nSmoothHP = 0; 
    if (xPrice.getValue(-1) != null) nSmoothHP = 0;
    else nSmoothHP = xPrice.getValue(0) - xPrice.getValue(-1);
    
    if (xHP.getValue(-5) != null) {
        nSmoothHP = (xHP.getValue(0) + 2 * xHP.getValue(-1) + 3 * xHP.getValue(-2)
                     + 3 * xHP.getValue(-3) + 2 * xHP.getValue(-4) + xHP.getValue(-5)) / 12;
    }

        ndelta = (-0.015) * getCurrentBarCount() + 0.5;
        if (ndelta < 0.1) ndelta = 0.1;


        
        if (getCurrentBarCount() > 12) {
                for (nN = 12; nN <= 60; nN++) {
                        nbeta = Math.cos(pi * (720 / nN) / 180);
                        ngamma = 1 / Math.cos(pi * (1440 * ndelta / nN) / 180);
                        nalpha = ngamma -  Math.sqrt(ngamma * ngamma - 1);
                        aQ[nN] = (0.5 * nN / 6.28318) * (nSmoothHP - nSmoothHP1);
                        aI[nN] = nSmoothHP;
                        aReal[nN] = 0.5 * (1 - nalpha) * (aI[nN] - aOlderI[nN])
                                    + nbeta * (1 + nalpha) * aOldReal[nN] - nalpha * aOlderReal[nN];
                        aImag[nN] = 0.5 * (1 - nalpha) * (aQ[nN] - aOlderQ[nN])
                                    + nbeta * (1 + nalpha) * aOldImag[nN] - nalpha * aOlderImag[nN];
                        aAmpl[nN] = (aReal[nN] * aReal[nN] + aImag[nN] * aImag[nN]);
                }
        }


        


        nMaxAmpl = aAmpl[12];
        for (nN = 12; nN <= 60; nN++) {
        if (aAmpl[nN] > nMaxAmpl) nMaxAmpl = aAmpl[nN];
        }

     
        for (nN = 12; nN <= 60; nN++) {
                if (nMaxAmpl != 0 && (aAmpl[nN] / nMaxAmpl) > 0) 
                    aDB[nN] = (-10) * Math.log(0.01 / (1 - 0.99 * aAmpl[nN] / nMaxAmpl)) / Math.log(10);
                aDB[nN] = 0.33 * aDB[nN] + 0.67 * aOldDB[nN];
                if (aDB[nN] > 20) aDB[nN] = 20;
        }

        nNum = 0;
        nDenom = 0;
        for (nN = 12; nN <= 60; nN++) {
                if (aDB[nN] <= 6) {
                        nNum = nNum + nN * (20 - aDB[nN]);
                        nDenom = nDenom + (20 - aDB[nN]);
                }
                if (nDenom != 0) {
            nDC = 0.5 * nNum / nDenom;
            aDC[0] = nDC;
        }
        }


        nDomCyc = Median(aDC, 5);
    if (bShowDC == true) {
        xResultArray[60] = nDomCyc;
    }

        for (nN = 12; nN <= 60; nN++) {
                if (aDB[nN] <= 10) {
                        nColor1 = Math.round(nLineR + aDB[nN] * (nFuzzR - nLineR) / 10);
                        nColor2 = Math.round(nLineG + aDB[nN] * (nFuzzG - nLineG) / 10);
                        nColor3 = Math.round(nLineB + aDB[nN] * (nFuzzB - nLineB) / 10);
                }
                
        if (aDB[nN] > 10) {
                        nColor1 = Math.round(nFuzzR * (2 - aDB[nN] / 10));
                        nColor2 = Math.round(nFuzzG * (2 - aDB[nN] / 10));
                        nColor3 = Math.round(nFuzzB * (2 - aDB[nN] / 10));
                }

                if (nN >= 12) {
            xResultArray[nResCounter++] = nN/2;
            setBarFgColor(Color.RGB(nColor1, nColor2, nColor3), nResCounter-1);
            setPlotType(PLOTTYPE_LINE, nResCounter-1); 
            setDefaultBarThickness(5, nResCounter-1);
        }    
        }



    
    return xResultArray; 
}

function resetVars() {    
    nRef_Global = 0;
    ndelta = 0.1;
    ngamma = 0;
    nalpha = 0;
    nbeta = 0;
    nN = 0;
    nPeriod = 0;
    nMaxAmpl = 0;
    nNum = 0;
    nDenom = 0;
    nDC = 0;
    nDomCyc = 0;
    nColor1 = 0;
    nColor2 = 0;
    nColor3 = 0;
    nalpha1 = 0;

    nSmoothHP = 0;
    nSmoothHP1 = 0;
    
    
    for (var i = 0; i < 61; i++) {
        xResultArray[i] = null;
        aI[i] = 0;
        aOldI[i] = 0;
        aOlderI[i] = 0;
        aQ[i] = 0;
        aOldQ[i] = 0;
        aOlderQ[i] = 0;
        aReal[i] = 0;
        aOldReal[i] = 0;
        aOlderReal[i] = 0;
        aImag[i] = 0;
        aOldImag[i] = 0;
        aOlderImag[i] = 0;
        aAmpl[i] = 0;
        aOldAmpl[i] = 0;
        aDB[i] = 0;
        aOldDB[i] = 0;
        aDC[i] = 0;
    }
    xResultArray[61] = null;
    
    return;
}


// calcHP globals
var nPrevHP = null;
var nCurrHP = null;

function Calc_HP(x, nAlpha1) {
    var nHP = null;
    
    if (getCurrentBarCount() <= 5 ) {
        nCurrHP = x.getValue(0);
        return nCurrHP;
    } else {
        if (x.getValue(-1) == null) return null;
        if (getBarState() == BARSTATE_NEWBAR) nPrevHP = nCurrHP;
        nCurrHP = ( 0.5*(1 + nAlpha1)*(x.getValue(0) - x.getValue(-1)) + nAlpha1*nPrevHP );
        return nCurrHP;
    }

}


function Median(myArray, Length) {
    var aArray = new Array(Length);
    var nMedian = null;

    for (var i = 0; i < Length; i++) {
        aArray[i] = myArray[i];
    }

    aArray = aArray.sort(compareNumbers);
    nMedian = aArray[Math.round((Length-1)/2)];
    return nMedian;
}

function compareNumbers(a, b) {
   return a - b
}

function verify() {
    var b = false;
    if (getBuildNumber() < 779) {
        drawTextAbsolute(5, 35, "This study requires version 8.0 or later.", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "error");
        drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=https://www.esignal.com/download/default.asp", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "upgrade");
        return b;
    } else {
        b = true;
    }
    return b;
}
--Jason Keck
eSignal, a division of Interactive Data Corp.
800 815-8256,
www.esignalcentral.com
GO BACK

AMIBROKER: CORONA CHARTS

In the article "Corona Charts" in this issue, John Ehlers further develops his earlier work on market cycles. A new kind of indicator is presented that uses a glow-like effect to present another dimension of data. Implementation of corona charts in AmiBroker Formula Language (AFL) is based on earlier AmiBroker code that helps detect dominant cycles in data. We have added a new parameter that allows you to switch between spectrum charts and corona charts for swing positions. The formula is presented in Listing 1. To use it, simply enter the code in the AmiBroker Formula Editor, then choose the Tools->Apply Indicator menu from the editor. You can use the parameters window (available from the right-click menu) to set the period for the high-pass filter and to switch the chart type. A sample chart is shown in Figure 5.

FIGURE 5: AMIBROKER, CORONA CHART. The daily chart of SPY is shown in the upper pane with a corona swing chart in the lower pane. A corona is displayed when the market is in a trend and there is little cyclic component.

LISTING 1

SetChartBkGradientFill( ColorRGB(0,0,0), ColorRGB(0,0,0)); 
PI = 3.1415926; 

Data = (H+L)/2; 

// detrending ( high-pass filter ) 
HFPeriods = Param("HP filter cutoff", 30, 20, 100 ); 
alpha1 = ( 1-sin(2*pi/HFPeriods) ) / cos( 2 * pi / HFPeriods ); 
HP = AMA2( Data - Ref( Data, -1 ), 0.5 * ( 1 + alpha1 ), alpha1 ); 

// 6-tap low-pass FIR filter 
SmoothHP  = ( HP + 2 * Ref( HP, -1 ) + 3 * Ref( HP, -2 ) + 
   3 * Ref( HP, -3 ) + 2 * Ref( HP, -4 ) + Ref( HP, -5 ) )/12; 

SmoothHPDiff = SmoothHP - Ref( SmoothHP, -1 ); 

x = BarIndex(); 

delta = -0.015 * x + 0.5; 
delta = Max( delta, 0.15 ); 

Q  = 0; 
Real = 0; 
Imag = 0; 
Ampl = 0; 
DB =  0; 

I = SmoothHP; 

MaxAmpl = 0; 

MinPeriod = 6; 
MaxPeriod = 30; 
PeriodStep = 0.5; 

for( N = MinPeriod; N <= MaxPeriod; N += PeriodStep ) 
{ 
   beta = cos( 2 * PI / N ); 
   Q = ( N / ( 2 * PI ) ) * SmoothHPDiff; 

   for( bar = 12; bar < BarCount; bar++ ) 
   { 
     gamma = 1 / cos( 4 * PI * delta[ bar ] / N ); 
     alpha = gamma - sqrt( gamma * gamma - 1 ); 
     
     Real[ bar ] = 0.5 * ( 1 - alpha ) * ( I[ bar ] - I[ bar - 1 ] ) + 
                   beta * ( 1 + alpha ) * Real[ bar - 1 ] - 
                   alpha * Real[ bar - 2 ]; 

     Imag[ bar ] = 0.5 * ( 1- alpha ) * ( Q[ bar ] - Q[ bar - 1 ] ) + 
                 beta * ( 1 + alpha ) * Imag[ bar - 1 ] - 
                 alpha * Imag[ bar - 2 ]; 
   } 

   Ampl = Real * Real + Imag * Imag; 
   MaxAmpl = Max( MaxAmpl, Ampl ); 
   VarSet("Ampl"+N, Ampl ); 
} 

CoronaSwingPos = ParamToggle("Chart Type", "Spectrum|Corona Swing Pos" ); 

// Plot Heat Map ( Spectrogram ) 
// and find dominant cycle 
DcNum = DcDenom = 0; 
for( N = MinPeriod; N <= MaxPeriod; N += PeriodStep ) 
{ 
   Ampl = VarGet("Ampl"+N); 

   db  = Nz( -10 * log10( 0.01 / ( 1 - 0.99 * Ampl / MaxAmpl ) ) ); 
   db = Min( db, 20 ) ; 

   Red = IIf( db <= 10, 255, 255 * ( 2 - db/10 ) ); 
   Green = IIf( db <= 10, 255 * ( 1 - db/10 ), 0 ); 

   if( NOT CoronaSwingPos ) 
      PlotOHLC( N, N, N-PeriodStep, N-PeriodStep, "", 
       ColorRGB( Red, Green, 0 ), styleCloud | styleNoLabel); 

   DcNum = DcNum + (db <= 6 ) * N * ( 20 - db ); 
   DcDenom = DcDenom + ( db <= 6 ) * ( 20 - db ); 
}     

DC = DcNum / DcDenom; 

if( NOT CoronaSwingPos ) 
{ 
  DomCycle = Median( DC, 5 ); 

  Plot( DomCycle, "Dominant Cycle", colorYellow); 
  Title = EncodeColor( colorWhite ) + "{{NAME}} - Spectrum - DC " + DomCycle; 
} 

if( CoronaSwingPos ) 
{ 
   DomCycle = Median( DC, 5 ); 
   DomCycle = Max( DomCycle, 6 ); 
   BP2 = 0; 
   DataDiff = Data - Ref( Data, -2 ); 

   for( bar = 10; bar < BarCount; bar++ ) 
   { 
     beta = cos( 2 * PI / domCycle[ bar ] ); 
     gamma = 1 / cos( 4 * PI * delta[ bar ] / DomCycle[ bar ] ); 
     alpha = gamma - sqrt( gamma ^ 2 - 1 ); 

     BP2[ bar ] = 0.5 * ( 1 - alpha ) * DataDiff[ bar ] +   
           beta * ( 1 + alpha ) * BP2[ bar - 1 ] - 
           alpha * BP2[ bar - 2 ]; 
   } 

   Q2 = ( domCycle / ( 2 * PI ) ) * ( BP2 - Ref( BP2, -1 ) ); 
   Lead60 = 0.5 * BP2 + 0.866 * Q2; 

   HL = HHV( Lead60, 50 ); 
   LL = LLV( Lead60, 50 ); 

   Psn = ( Lead60 - LL )/( HL - LL ); 

   HL = HHV( Psn, 20 ); 
   LL = LLV( Psn, 20 ); 

   Width = IIf( HL - LL > 0.85, 0.85, ( HL - LL ) ); 

  for( N = 0; N < 50; N++ ) 
  { 
     Raster =  log( Width/( 0.2 + abs( Psn - N/50 ) ) );   

     Raster = Min( 2, Max( 0, Raster ) ); 
     CR =  128*Raster;//IIf( Raster <= 10,  Raster, 255 -  Raster ); 
     y = 0.02 * N; 
     PlotOHLC( y, y+0.01, y -0.01, y-0.01, "", ColorRGB( 0, CR, CR ), 
      styleCloud | styleNoLabel ); 
  } 
  Plot( Psn, "", ColorRGB( 0, 255, 255 )); 
  Title = EncodeColor( colorWhite ) + "{{NAME}} - Corona Swing Position " + Psn; 
} 

GraphZOrder = 1; 

--Tomasz Janeczko, AmiBroker.com
www.amibroker.com
GO BACK

NEUROSHELL TRADER: CORONA CHARTS

John Ehlers's corona chart indicators can be easily implemented in NeuroShell Trader using NeuroShell Trader's ability to call functions written in standard languages like C, C++, Power Basic, or Delphi. Because the code for this tip is so lengthy, we have elected to use that facility instead of using our "point and click" Indicator Wizard. After moving the EasyLanguage code given in the article to your preferred compiler and creating a dynamic link library (DLL) from it, you can insert the resulting indicators as follows:

  1. Select "New Indicator..." from the Insert menu.
  2. Choose the External Program & Library Calls category.
  3. Select the appropriate External DLLL Call indicator.
  4. Set up the parameters to match your dynamic link library.
  5. Select the Finished button.
A sample chart is shown in Figure 6. Dynamic trading systems can be easily created in NeuroShell Trader by combining the corona chart indicators with the adaptive-length indicators available in John Ehlers's Cybernetic and Mesa8 NeuroShell Trader add-ons. Ehlers suggests that adaptive-length indicators linked to the cycle period indicator, when combined with NeuroShell Trader's genetic optimizer, could produce very robust systems. Similar strategies can also be created using the Dominant Cycle indicator found in John Ehlers's Mesa8 NeuroShell Trader Add-on. Users of NeuroShell Trader can go to the STOCKS & COMMODITIES section of the NeuroShell Trader free technical support website to download a copy of any Traders' Tip, including the compiled code we made for this article.

FIGURE 6: NEUROSHELL, CORONA CHART. Here is a sample NeuroShell chart demonstrating the corona charts indicators.
--Marge Sherald, Ward Systems Group, Inc.
301 662-7950, sales@wardsystems.com
www.neuroshell.com
GO BACK

WORDEN BROTHERS BLOCKS: THE MIDAS TOUCH

Note: To use the indicators and charts in this Traders' Tip, you will need the free Blocks software. Go to www.Blocks.com to download the software and get free US stock charts and scans. The MIDAS and I-MIDAS indicators from Andrew Coles's article in the September 2008 issue, "The Midas Touch," can be implemented in Blocks using RealCode. A sample chart is shown in Figure 7. RealCode is based on the Microsoft Visual Basic.Net framework and uses the Visual Basic (VB) language syntax. RealCode is compiled into a .Net assembly and run by the Blocks application. Unlike the scripting language that other trading applications use, RealCode is fully compiled and runs at the same machine language level as the Blocks application itself. This gives you unmatched performance running at the same speed as if we (the developers of Blocks) wrote the code ourselves, with the flexibility of "run-time development and assembly" that you get by writing your own custom code.

FIGURE 7: WORDEN BROTHERS BLOCKS, MIDAS CHARTS. Here, the MIDAS is applied to daily chart of AAPL. After you plot the first instance of MIDAS, you can right-click on the indicator, select "copy," then paste it into the pane again. Then adjust the color and date/time settings for each plot.

MIDAS/I-MIDAS code:


'# Year = UserInput.Integer = 2008
'# Month = UserInput.Integer = 1
'# Day = UserInput.Integer = 1
'# Leave the Hour, Minute, Second values set to 0 for MIDAS.
'# Hour = UserInput.Integer = 0
'# Minute = UserInput.Integer = 0
'# Second = UserInput.integer = 0
Static StartDate As Date
Static CumPrice As Double
Static CumVolume As Double
If isFirstBar Then
        StartDate = New Date(Year,Month,Day,Hour,Minute,Second)
        CumPrice = 0
        CumVolume = 0
End If
If CurrentDate >= StartDate Then
        CumPrice += Price.Last * Volume
        CumVolume += Volume
        Plot = CumPrice / CumVolume
Else
        Plot = Single.NaN
End If

To download the RealCode Reference manual as well as the Blocks software, go to www.Blocks.com.
--Bruce Loebrich and Patrick Argo
Worden Brothers, Inc.
GO BACK

AIQ: MOCS EXIT INDICATOR

The AIQ code for Michael J. Carr's Mocs exit indicator from his August 2008 article, "Relative Strength As A Selling Tool," is given here. Using relative strength as an exit indicator can be very effective and is often overlooked when we are designing exits for our strategies. One exit strategy that uses relative strength is the MOCS exit, originally developed by Christopher Hendrix. As Carr discusses in his August 2008 article, the relative strength of the stock to the S&P 500 index (RS_SPX) is inserted into the MACD formula in place of the price. In coding the MACD of the RS_SPX, I generated three indicators as follows:

MOCS = 12-bar EMA of RS_SPX &ndash; 26 bar EMA of RS_SPX
sigMOCS = 9-bar EMA of MOCS
difMOCS = MOCS &ndash; sigMOCS
I then used these indicators in various combinations to come up with three exits in addition to the one suggested by the author. The table in Figure 8 compares the results of a backtest of a 30-day breakout system on the NASDAQ 100 stocks from 10/11/02 to 9/12/08. LX1 is the exit mentioned in the article and is the fastest of the four exits. However, the best performing exit was LX2 which uses only the MOCS indicator and exits when it turns negative. The LX3 and LX4 exits are combinations of the MOCS and the difMocs. The slowest exits proved to be the ones with the best reward-to-risk ratios.
!! RELATIVE STRENGTH AS A SELLING TOOL
! Author: Michael J. Carr, CMT, TASC Aug 2008
! Coded by: Richard Denning 9/15/08
! www.TradersEdgeSystems.com

C is [close].

! MOMENTUM OF COMPARATIVE STRENGTH (MOCS)
RSspx is C / tickerUDF("SPX",C)*100000.
RSema12 is expavg(RSspx,12).
RSema26 is expavg(RSspx,26).

! MACD FORMULA APPLIED TO RS
MOCS is RSema12 - RSema26.
sigMOCS is expavg(MOCS,9).

difMOCS is  MOCS - sigMOCS.

! ENTRY RULES FOR TESTING EXITS:
LE1 if C > highresult(C,30,1) and difMOCS > 0 and MOCS > 0.
LE2 if LE1.
LE3 if LE1.
LE4 if LE1.

! VARIOUS EXITS USING MOCS:
LX1 if difMOCS < 0.
LX2 if  MOCS < 0.       
LX3 if MOCS < 0 or countof(difMOCS < 0,6)=6 .
LX4 if MOCS < 0 and countof(difMOCS < 0,6)=6 .
The code can be downloaded from the AIQ website at www.aiqsystems.com and also from www.tradersedge systems.com/traderstips.htm.

FIGURE 8: AIQ, MOCS EXIT INDICATOR. Here is a comparison of four relative strength exits using the MOCS indicator. Exit LX2 had the best metrics compared to the other three approaches.
--Richard Denning
richard.denning@earthlink.net for AIQ Systems
GO BACK

TRADERSTUDIO: CORONA CHARTS

I have prepared TradersStudio code for John Ehlers's article in this issue, "Corona Charts." Figure 9 shows the four indicators as they appear on a QuickChart in TradersStudio. The corona effects do not show on the indicator panels but instead are shown on a color report, as seen in Figures 10 and 11. These two figures show the current values for the four indicators and also their relative signal strength, also known as the corona, as represented by the color of the report cell.

FIGURE 9: TRADERSTUDIO, CORONA CHARTS. Here are Ehlers's four indicators as shown on a chart of the emini S&P 500 futures contract.

FIGURE 10: TRADERSTUDIO, COLOR REPORT. Here is a color report on a portfolio of futures as of September 12, 2008.

FIGURE 11: TRADERSTUDIO, COLOR REPORT. Here is a color report on a portfolio of futures as of May 1, 2008.

I ran the report for two different time periods on a small futures portfolio to show how the colors will differ. Figure 10 shows the status as of 9/12/2008 and Figure 11 shows the status as of 5/1/2008. This type of report allows one to quickly spot the markets that have the best combination of indicators and their respective colors, which represent the signal strength. The color key is as follows:

 Light green = Strong signal with little or no fuzz
Light yellow = Moderately strong signal with some fuzz
      Yellow = Weaker signal with more fuzz
      Yellow = Even weaker signal with even more fuzz
         Red = Very weak signal with a high level of fuzz
       White = No rating regarding signal strength
The color levels and colors can be adjusted by the user by changing the parameters in the code. Note that the first column, which displays the dominant cycle period, does not have the color applied and hence it is all white.

The code can be downloaded from the TradersStudio website at www.TradersStudio.com ->Traders Resources->FreeCode and also from www.TradersEdgeSystems.com/traderstips.htm.

TradersStudioCode DomCyc.txt

Function EhlersDC(colorRGB)
    Dim price As BarArray, DC As BarArray
    Dim HP As BarArray, SmoothHP As BarArray
    Dim delta As BarArray, gamma As BarArray
    Dim alpha As BarArray, beta As BarArray
    Dim alpha1 As BarArray, MaxAmpl As BarArray
    Dim Num As BarArray, Denom As BarArray
    Dim DomCyc As BarArray
    
    Dim fuzzRGB, lineRGB, maxColorRGB
    Dim N, TScurrentBar, myDate   
    
    Dim I As Array, OldI As Array, OlderI As Array
    Dim Q As Array, OldQ As Array, OlderQ As Array
    Dim Real As Array, OldReal As Array, OlderReal As Array
    Dim Imag As Array, OldImag As Array, OlderImag As Array
    Dim Ampl As Array, OldAmpl As Array
    Dim DB As Array, OldDB As Array
    Dim aDC As Array, color As Array
    
    ReDim (I, 61)
    ReDim (OldI, 61)
    ReDim (OlderI, 61)
    ReDim (Q, 61)
    ReDim (OldQ, 61)
    ReDim (OlderQ, 61)
    ReDim (Real, 61)
    ReDim (OldReal, 61)
    ReDim (OlderReal, 61)
    ReDim (Imag, 61)
    ReDim (OldImag, 61)
    ReDim (OlderImag, 61)
    ReDim (Ampl, 61)
    ReDim (OldAmpl, 61)
    ReDim (DB, 61)
    ReDim (OldDB, 61)
    ReDim (aDC,5)
    ReDim (color,61)
    
    If BarNumber=FirstBar Then
        gamma = 0
        alpha = 0
        beta = 0
        N = 0
        MaxAmpl = 0
        Num = 0
        Denom = 0
        DC = 0
        DomCyc = 0
        alpha1 = 0
        HP = 0
        SmoothHP = 0
        For N = 0 To 60
            I[N] = 0
            OldI[N] = 0
            OlderI[N] = 0
            Q[N] = 0
            OldQ[N] = 0
            OlderQ[N]=0
            Real[N] = 0
            OldReal[N] = 0
            OlderReal[N] = 0
            Imag[N] = 0
            OldImag[N] = 0
            OlderImag[N] = 0
            Ampl[N] = 0
            OldAmpl[N] = 0
            DB[N] = 0
            OldDB[N] = 0
            color[N] = 0
        Next
    End If
    
    price = (H+L)/2
    delta = 0.1
    fuzzRGB = 190
    lineRGB = 255
    TScurrentBar = CurrentBar + 1
    myDate = FormatDateTime(Date)
      
    I = GValue201
    OldI = GValue202
    OlderI = GValue203
    Q = GValue204
    OldQ = GValue205
    OlderQ = GValue206
    Real = GValue207
    OldReal = GValue208
    OlderReal = GValue209
    Imag = GValue210
    OldImag = GValue211
    OlderImag = GValue212
    Ampl = GValue213
    OldAmpl = GValue214
    DB = GValue215
    OldDB = GValue216

    alpha1 = (1 - Sin(DegToRad(360/30))) / Cos(DegToRad(360/30))
    HP = .5*(1 + alpha1)*(price - price[1]) + alpha1*HP[1]
    SmoothHP = (HP + 2*HP[1] + 3*HP[2] + 3*HP[3] + 2*HP[4] + HP[5]) / 12
    If TScurrentBar < 7 Then SmoothHP = price - price[1]
    If TScurrentBar = 1 Then SmoothHP = 0
    delta = -.015*(TScurrentBar) + .5
    If delta < .1 Then delta = .1
    
If TScurrentBar > 12  Then
    For N = 12 To 60
        beta = Cos(DegToRad(720 / N))
        gamma = 1 / Cos(DegToRad(1440 * delta / N))
        alpha = gamma - Sqr(gamma * gamma - 1)
        Q[N] = (.5*N / 6.28318)*(SmoothHP - SmoothHP[1])
        I[N] = SmoothHP
        Real[N] = .5*(1 - alpha)*(I[N] - OlderI[N]) + beta*(1 + alpha)*OldReal[N] - alpha*OlderReal[N]
        Imag[N] = .5*(1 - alpha)*(Q[N] - OlderQ[N]) + beta*(1 + alpha)*OldImag[N] - alpha*OlderImag[N]
        Ampl[N] = (Real[N]*Real[N] + Imag[N]*Imag[N])  
    Next

    For N = 12 To 60
        OlderI[N] = OldI[N]
        OldI[N] = I[N]
        OlderQ[N] = OldQ[N]
        OldQ[N] = Q[N]
        OlderReal[N] = OldReal[N]
        OldReal[N] = Real[N]
        OlderImag[N] = OldImag[N]
        OldImag[N] = Imag[N]
        OldAmpl[N] = Ampl[N]
        OldDB[N] = DB[N]
    Next
    
    MaxAmpl = Ampl[12]
    
    For N = 12 To 60
        If Ampl[N] > MaxAmpl Then MaxAmpl = Ampl[N]
    Next
    
    For N = 12 To 60
        If MaxAmpl <> 0 And (Ampl[N] / MaxAmpl) > 0 Then
            DB[N] = -10*Log(.01 / (1 - .99*Ampl[N] / MaxAmpl)) / Log(10)
        End If
        DB[N] = .33*DB[N] + .67*OldDB[N]
        If DB[N] > 20 Then DB[N] = 20
    Next
    
    Num = 0
    Denom = 0
    
    For N = 12 To 60
        If DB[N] <= 6 Then
            Num = Num + N*(20 - DB[N])
            Denom = Denom + (20 - DB[N])
        End If
        If Denom <> 0 Then DC = .5*Num / Denom
     Next   
    For N = 0 To 4
        aDC[N] = DC[N]
    Next
    DomCyc = Median(aDC)
   
EhlersDC = DomCyc
    
    For N = 12 To 60 
        If DB[N] <= 10 Then color[N] = lineRGB + DB[N]*(fuzzRGB - lineRGB) / 10
        If DB[N] > 10 Then color[N] = fuzzRGB*(2 - DB[N] / 10)  
        If color[N] > maxColorRGB Then maxColorRGB = color[N]
    Next
    
colorRGB = maxColorRGB
    
End If

    GValue201 = I
    GValue202 = OldI
    GValue203 = OlderI
    GValue204 = Q
    GValue205 = OldQ
    GValue206 = OlderQ
    GValue207 = Real
    GValue208 = OldReal
    GValue209 = OlderReal
    GValue210 = Imag
    GValue211 = OldImag
    GValue212 = OlderImag
    GValue213 = Ampl
    GValue214 = OldAmpl
    GValue215 = DB
    GValue216 = OldDB

End Function

_________________________________________________________________________________________
Sub EhlersDomCycle()
Dim colorRGB
Dim EDC As BarArray
Dim myDate
myDate = FormatDateTime(Date)
EDC = EhlersDC(colorRGB)
plot1(EDC)
End Sub
_________________________________________________________________________________________






Function EhlersSP(byref colorRGB)
    Dim price As BarArray, DC As BarArray
    Dim HP As BarArray, SmoothHP As BarArray
    Dim delta As BarArray, gamma As BarArray
    Dim alpha As BarArray, beta As BarArray
    Dim alpha1 As BarArray, MaxAmpl As BarArray
    Dim Num As BarArray, Denom As BarArray
    Dim DomCyc As BarArray, gamma2 As BarArray
    Dim alpha2 As BarArray, beta2 As BarArray
    Dim delta2 As BarArray, BP2 As BarArray
    Dim Q2 As BarArray, Lead60 As BarArray
    Dim HL As BarArray, LL As BarArray
    Dim Psn As BarArray, Width As BarArray
    
    Dim fuzzRGB, lineRGB, maxColorRGB
    Dim N, TScurrentBar, myDate, count  
     
    Dim I As Array, OldI As Array, OlderI As Array
    Dim Q As Array, OldQ As Array, OlderQ As Array
    Dim Real As Array, OldReal As Array, OlderReal As Array
    Dim Imag As Array, OldImag As Array, OlderImag As Array
    Dim Ampl As Array, OldAmpl As Array
    Dim DB As Array, OldDB As Array
    Dim Raster As Array, oldRaster As Array
    

    Dim aDC As Array, aRange As Array
    Dim color As Array
    
    ReDim (I, 61)
    ReDim (OldI, 61)
    ReDim (OlderI, 61)
    ReDim (Q, 61)
    ReDim (OldQ, 61)
    ReDim (OlderQ, 61)
    ReDim (Real, 61)
    ReDim (OldReal, 61)
    ReDim (OlderReal, 61)
    ReDim (Imag, 61)
    ReDim (OldImag, 61)
    ReDim (OlderImag, 61)
    ReDim (Ampl, 61)
    ReDim (OldAmpl, 61)
    ReDim (DB, 61)
    ReDim (OldDB, 61)
    ReDim (Raster, 51)
    ReDim (oldRaster, 51)
    
    ReDim (aDC,5)
    ReDim (aRange,5)
    ReDim (color,51)
    
    If BarNumber=FirstBar Then
        gamma = 0
        alpha = 0
        beta = 0
        N = 0
        MaxAmpl = 0
        Num = 0
        Denom = 0
        DC = 0
        DomCyc = 0
        alpha1 = 0
        HP = 0
        SmoothHP = 0
        gamma2 = 0
        alpha2 = 0
        beta2 = 0
        delta2 = 0
        BP2 = 0
        Q2 = 0
        Lead60 = 0
        HL = 0
        LL = 0
        Psn = 0
        Width = 0
        
        For N = 0 To 60
            I[N] = 0
            OldI[N] = 0
            OlderI[N] = 0
            Q[N] = 0
            OldQ[N] = 0
            OlderQ[N]=0
            Real[N] = 0
            OldReal[N] = 0
            OlderReal[N] = 0
            Imag[N] = 0
            OldImag[N] = 0
            OlderImag[N] = 0
            Ampl[N] = 0
            OldAmpl[N] = 0
            DB[N] = 0
            OldDB[N] = 0
         Next
         
        For N = 0 To 50
            Raster[N] = 0
            oldRaster[N] = 0
            color[N] = 0
        Next
    End If
    
    price = (H+L)/2
    delta = 0.1
    delta2 = 0.1
    fuzzRGB = 190
    lineRGB = 255
    TScurrentBar = CurrentBar + 1
    myDate = FormatDateTime(Date)
        
    I = GValue301
    OldI = GValue302
    OlderI = GValue303
    Q = GValue304
    OldQ = GValue305
    OlderQ = GValue306
    Real = GValue307
    OldReal = GValue308
    OlderReal = GValue309
    Imag = GValue310
    OldImag = GValue311
    OlderImag = GValue312
    Ampl = GValue313
    OldAmpl = GValue314
    DB = GValue315
    OldDB = GValue316
    Raster = Gvalue317
    oldRaster = Gvalue318  

    alpha1 = (1 - Sin(DegToRad(360/30))) / Cos(DegToRad(360/30))
    HP = .5*(1 + alpha1)*(price - price[1]) + alpha1*HP[1]
    SmoothHP = (HP + 2*HP[1] + 3*HP[2] + 3*HP[3] + 2*HP[4] + HP[5]) / 12
    If TScurrentBar < 7 Then SmoothHP = price - price[1]
    If TScurrentBar = 1 Then SmoothHP = 0
    delta = -0.015*(TScurrentBar) + 0.5
    If delta < 0.1 Then delta = 0.1
    
If TScurrentBar > 12  Then 'begin concdition A
    For N = 12 To 60
        beta = Cos(DegToRad(720 / N))
        gamma = 1 / Cos(DegToRad(1440 * delta / N))
        alpha = gamma - Sqr(gamma * gamma - 1)
        Q[N] = (.5*N / 6.28318)*(SmoothHP - SmoothHP[1])
        I[N] = SmoothHP
        Real[N] = .5*(1 - alpha)*(I[N] - OlderI[N]) + beta*(1 + alpha)*OldReal[N] - alpha*OlderReal[N]
        Imag[N] = .5*(1 - alpha)*(Q[N] - OlderQ[N]) + beta*(1 + alpha)*OldImag[N] - alpha*OlderImag[N]
        Ampl[N] = (Real[N]*Real[N] + Imag[N]*Imag[N])
    Next

    For N = 12 To 60
        OlderI[N] = OldI[N]
        OldI[N] = I[N]
        OlderQ[N] = OldQ[N]
        OldQ[N] = Q[N]
        OlderReal[N] = OldReal[N]
        OldReal[N] = Real[N]
        OlderImag[N] = OldImag[N]
        OldImag[N] = Imag[N]
        OldAmpl[N] = Ampl[N]
        OldDB[N] = DB[N]
    Next
    
    For N = 1 To 50 
        oldRaster[N] = Raster[N]
    Next
    

    MaxAmpl = Ampl[12]
    
    For N = 12 To 60
        If Ampl[N] > MaxAmpl Then MaxAmpl = Ampl[N]
    Next
    
    For N = 12 To 60
        If MaxAmpl <> 0 And (Ampl[N] / MaxAmpl) > 0 Then
            DB[N] = -10*Log(.01 / (1 - .99*Ampl[N] / MaxAmpl)) / Log(10)
        End If
        DB[N] = .33*DB[N] + .67*OldDB[N]
        If DB[N] > 20 Then DB[N] = 20
    Next
    
    Num = 0
    Denom = 0
    
    For N = 12 To 60
        If DB[N] <= 6 Then
            Num = Num + N*(20 - DB[N])

            Denom = Denom + (20 - DB[N])
        End If
        If Denom <> 0 Then DC = .5*Num / Denom
     Next   
    For N = 0 To 4
        aDC[N] = DC[N]
    Next
    DomCyc = Median(aDC)
    If DomCyc < 6 Then DomCyc = 6
    
    beta2 = Cos(DegToRad(360 / DomCyc))
    gamma2 = 1 / Cos(DegToRad(720*delta2 / DomCyc))
    alpha2 = gamma2 - Sqr(gamma2*gamma2 - 1)
    BP2 = 0.5*(1 - alpha2)*(price - price[2]) + beta2*(1 + alpha2)*BP2[1] - alpha2*BP2[2]
    Q2 = (DomCyc / 6.28318)*(BP2 - BP2[1])
    Lead60 = 0.5*BP2 + 0.866*Q2
    HL = Lead60
    LL = Lead60
    
    For count = 0 To 50 
        If Lead60[count] > HL Then HL = Lead60[count]
        If Lead60[count] < LL Then LL = Lead60[count]
    Next
    
    Psn = (Lead60 - LL) / (HL - LL)
    HL = Psn
    LL = Psn

    For count = 0 To 20 
        If Psn[count] > HL Then HL = Psn[count]
        If Psn[count] < LL Then LL = Psn[count]
    Next
    
    If HL - LL > 0.85 Then Width = 0.01 Else Width = 0.15*(HL - LL)

EhlersSP = (10*Psn-5)  

    For N = 1 To 50 
        Raster[N] = 20 
        If Width > 0 Then
            If N < Round(50*Psn,0) Then Raster[N] = 0.5*((((20*Psn - 0.4*N)/ Width) ^ 0.95) + 0.5*oldRaster[N]) 
            If N > Round(50*Psn,0) Then Raster[N] = 0.5*((((-20*Psn + 0.4*N)/ Width) ^ 0.95) + 0.5*oldRaster[N]) 
        End If
        If N = Round(50*Psn,0) Then Raster[N] = 0.5*oldRaster[N] 
        If Raster[N] < 0 Then Raster[N] = 0 
        If Raster[N] > 20 Then Raster[N] = 20 
        If HL - LL > 0.8 Then Raster[N] = 20 
        oldRaster[N] = Raster[N] 
    Next

 For N = 1 To 50 
    If Raster[N] <= 10 Then 
        color[N] = lineRGB + Raster[N]*(fuzzRGB - lineRGB) / 10
    End If
    If Raster[N] > 10 Then 
        color[N] = fuzzRGB*(2 - Raster[N] / 10)
    End If
    If color[N] > maxColorRGB Then maxColorRGB = color[N]  
Next

colorRGB = maxColorRGB   

End If 'end condition A

    GValue301 = I
    GValue302 = OldI
    GValue303 = OlderI
    GValue304 = Q
    GValue305 = OldQ
    GValue306 = OlderQ
    GValue307 = Real
    GValue308 = OldReal
    GValue309 = OlderReal
    GValue310 = Imag
    GValue311 = OldImag
    GValue312 = OlderImag
    GValue313 = Ampl
    GValue314 = OldAmpl
    GValue315 = DB
    GValue316 = OldDB
    Gvalue317 = Raster
    Gvalue318 = oldRaster

End Function
__________________________________________________________________________________________
Sub EhlersSwingPosition()
Dim colorRGB
Dim ESP As BarArray
Dim myDate
myDate = FormatDateTime(Date)
ESP = EhlersSP(colorRGB)
plot1(ESP)
End Sub
____________________________________________________________________________________________
'








Function EhlersTV(byref colorRGB)
    Dim price As BarArray, DC As BarArray
    Dim HP As BarArray, SmoothHP As BarArray
    Dim delta As BarArray, gamma As BarArray
    Dim alpha As BarArray, beta As BarArray
    Dim alpha1 As BarArray, beta1 As BarArray
    Dim gamma1 As BarArray, delta1 As BarArray
    Dim alpha2 As BarArray, MaxAmpl As BarArray
    Dim Num As BarArray, Denom As BarArray
    Dim DomCyc As BarArray,IP As BarArray
    Dim Q1 As BarArray, ampl2 As BarArray
    Dim trend As BarArray, ratio As BarArray
    Dim TV As BarArray, width As BarArray
    Dim fuzzRGB, lineRGB, maxColorRGB
    Dim  N, TScurrentBar, myDate   
    
    Dim I As Array, OldI As Array, OlderI As Array
    Dim Q As Array, OldQ As Array, OlderQ As Array
    Dim Real As Array, OldReal As Array, OlderReal As Array
    Dim Imag As Array, OldImag As Array, OlderImag As Array
    Dim Ampl As Array, OldAmpl As Array
    Dim DB As Array, OldDB As Array
    Dim Raster As Array, oldRaster As Array
    Dim aDC As Array, color As Array
    ReDim (I, 61)
    ReDim (OldI, 61)
    ReDim (OlderI, 61)
    ReDim (Q, 61)
    ReDim (OldQ, 61)
    ReDim (OlderQ, 61)
    ReDim (Real, 61)
    ReDim (OldReal, 61)
    ReDim (OlderReal, 61)
    ReDim (Imag, 61)
    ReDim (OldImag, 61)
    ReDim (OlderImag, 61)
    ReDim (Ampl, 61)
    ReDim (OldAmpl, 61)
    ReDim (DB, 61)
    ReDim (OldDB, 61)
    ReDim (Raster, 51)
    ReDim (oldRaster, 51)
    
    ReDim (aDC,5)
    ReDim (color,51)
    
    If BarNumber=FirstBar Then
        gamma = 0
        alpha = 0
        beta = 0
        delta = 0.1
        alpha1 = 0
        beta1 = 0
        gamma1 = 0
        delta1 = 0
        alpha2 = 0    
        N = 0
        MaxAmpl = 0
        Num = 0
        Denom = 0
        DC = 0
        DomCyc = 0
        alpha1 = 0
        HP = 0
        SmoothHP = 0
        IP = 0
        Q1 = 0
        ampl2 = 0
        trend = 0
        ratio = 0
        TV = 0
        width = 0
        For N = 0 To 60
            I[N] = 0
            OldI[N] = 0
            OlderI[N] = 0
            Q[N] = 0
            OldQ[N] = 0
            OlderQ[N]=0
            Real[N] = 0
            OldReal[N] = 0
            OlderReal[N] = 0
            Imag[N] = 0
            OldImag[N] = 0
            OlderImag[N] = 0
            Ampl[N] = 0
            OldAmpl[N] = 0
            DB[N] = 0
            OldDB[N] = 0
        Next
        For N = 0 To 50
            Raster[N] = 0
            oldRaster[N] = 0
            color[N] = 0
        Next
    End If
    
    price = (H+L)/2
    delta1 = 0.1
    fuzzRGB = 190
    lineRGB = 255
    TScurrentBar = CurrentBar + 1
    myDate = FormatDateTime(Date)
        
    I = GValue501
    OldI = GValue502
    OlderI = GValue503
    Q = GValue504
    OldQ = GValue505
    OlderQ = GValue506
    Real = GValue507
    OldReal = GValue508
    OlderReal = GValue509
    Imag = GValue510
    OldImag = GValue511
    OlderImag = GValue512
    Ampl = GValue513
    OldAmpl = GValue514
    DB = GValue515
    OldDB = GValue516
    Raster = Gvalue517
    oldRaster = Gvalue518

    alpha1 = (1 - Sin(DegToRad(360/30))) / Cos(DegToRad(360/30))
    HP = .5*(1 + alpha1)*(price - price[1]) + alpha1*HP[1]
    SmoothHP = (HP + 2*HP[1] + 3*HP[2] + 3*HP[3] + 2*HP[4] + HP[5]) / 12
    If TScurrentBar < 7 Then SmoothHP = price - price[1]
    If TScurrentBar = 1 Then SmoothHP = 0
    delta = -.015*(TScurrentBar) + .5
    If delta < .1 Then delta = .1
    
If TScurrentBar > 12  Then  'begin condition A
    For N = 12 To 60
        beta = Cos(DegToRad(720 / N))
        gamma = 1 / Cos(DegToRad(1440 * delta / N))
        alpha = gamma - Sqr(gamma * gamma - 1)
        Q[N] = (.5*N / 6.28318)*(SmoothHP - SmoothHP[1])
        I[N] = SmoothHP
        Real[N] = .5*(1 - alpha)*(I[N] - OlderI[N]) + beta*(1 + alpha)*OldReal[N] - alpha*OlderReal[N]
        Imag[N] = .5*(1 - alpha)*(Q[N] - OlderQ[N]) + beta*(1 + alpha)*OldImag[N] - alpha*OlderImag[N]
        Ampl[N] = (Real[N]*Real[N] + Imag[N]*Imag[N])  
    Next

    For N = 12 To 60
        OlderI[N] = OldI[N]
        OldI[N] = I[N]
        OlderQ[N] = OldQ[N]
        OldQ[N] = Q[N]
        OlderReal[N] = OldReal[N]
        OldReal[N] = Real[N]
        OlderImag[N] = OldImag[N]
        OldImag[N] = Imag[N]
        OldAmpl[N] = Ampl[N]
        OldDB[N] = DB[N]
    Next
    
    For N = 1 To 50 
        oldRaster[N] = Raster[N]
    Next
    
    MaxAmpl = Ampl[12]
    
    For N = 12 To 60
        If Ampl[N] > MaxAmpl Then MaxAmpl = Ampl[N]
    Next
    
    For N = 12 To 60
        If MaxAmpl <> 0 And (Ampl[N] / MaxAmpl) > 0 Then
            DB[N] = -10 * Log(0.01 / (1 - 0.99 * Ampl[N] / MaxAmpl)) / Log(10)
        End If
        DB[N] = .33*DB[N] + .67*OldDB[N]
        If DB[N] > 20 Then DB[N] = 20
    Next
    
    Num = 0
    Denom = 0
    
    For N = 12 To 60
        If DB[N] <= 6 Then
            Num = Num + N*(20 - DB[N])
            Denom = Denom + (20 - DB[N])
        End If

        If Denom <> 0 Then DC = .5*Num / Denom
    Next 
 
    For N = 0 To 4
        aDC[N] = DC[N]
    Next

    DomCyc = Median(aDC)
    If DomCyc < 6 Then DomCyc = 6
    
'Filter Bandpass component
    beta1 = Cos(DegToRad(360 / DomCyc)) 
    gamma1 = 1 / Cos(DegToRad(720*delta1 / DomCyc) ) 
    alpha2 = gamma1 - Sqr(gamma1*gamma1 - 1) 
    IP = 0.5*(1 - alpha2)*(price - price[2]) + beta1*(1 + alpha2)*IP[1] - alpha2*IP[2] 

'Quadrature component is derivative of InPhase component divided by omega
    Q1 = (DomCyc / 6.28318)*(IP - IP[1]) 
    
'Pythagorean theorem to establish cycle amplitude
    ampl2 = Sqr(IP*IP + Q1*Q1)    
    
'Trend amplitude taken over the cycle period
    trend = price - price[CInt(Round(DomCyc,0)) - 1] 
    If trend <> 0 And ampl2 <> 0 Then ratio = 0.33 * trend / ampl2 + 0.67 * ratio[1] 
    If ratio > 10 Then ratio = 10 
    If ratio < -10 Then ratio = -10 
    TV = 0.05 * (ratio + 10) 
    If TV < 0.3 Or TV > 0.7 Then width = 0.01 
    If TV >= 0.3 And TV < 0.5 Then width = TV - 0.3 
    If TV > 0.5 And TV <= 0.7 Then width = -TV + 0.7 
    
EhlersTV = (20*TV-10)
   
For N = 1 To 50 
    Raster[N] = 20 
    If width > 0 Then
        If N < Round(50*TV,0) Then 
            Raster[N] = 0.8*((((20*TV - 0.4*N)/ width) ^ 0.85) + 0.2*oldRaster[N]) 
        End If
        If N > Round(50*TV,0) Then 
            Raster[N] = 0.8*((((-20*TV + 0.4*N)/ width) ^ 0.85) + 0.2*oldRaster[N]) 
        End If
    End If
    If N = Round(50*TV,0) Then Raster[N] = 0 + 0.5*oldRaster[N] 
    If Raster[N] < 0 Then Raster[N] = 0 
    If Raster[N] > 20 Or TV < 0.3 Or TV > 0.7 Then Raster[N] = 20 
Next 

For N = 1 To 50 
    If Raster[N] <= 10 Then 
        color[N] = lineRGB + Raster[N]*(fuzzRGB - lineRGB) / 10
    End If
    If Raster[N] > 10 Then 
        color[N] = fuzzRGB*(2 - Raster[N] / 10)
    End If
    If color[N] > maxColorRGB Then maxColorRGB = color[N]
Next

colorRGB = maxColorRGB
    
End If      'end condition A

    GValue501 = I

    GValue502 = OldI
    GValue503 = OlderI
    GValue504 = Q
    GValue505 = OldQ
    GValue506 = OlderQ
    GValue507 = Real
    GValue508 = OldReal
    GValue509 = OlderReal
    GValue510 = Imag
    GValue511 = OldImag
    GValue512 = OlderImag
    GValue513 = Ampl
    GValue514 = OldAmpl
    GValue515 = DB
    GValue516 = OldDB
    Gvalue517 = Raster
    Gvalue518 = oldRaster

End Function
__________________________________________________________________________________

sub EhlersTrendVigor()
Dim colorRGB
Dim ETV As BarArray
Dim myDate
myDate = FormatDateTime(Date)
ETV = EhlersTV(colorRGB)
plot1(ETV)
End Sub
__________________________________________________________________________________






Sub ColorSignalStrength()
    
    Dim color1, color2, color3,color4
    Dim colorRGB1, colorRGB2, colorRGB3, colorRGB4
    Dim EDC As BarArray, ESP As BarArray
    Dim ESNR As BarArray, ETV As BarArray
    Dim myDate
    
    myDate = FormatDateTime(Date)
    EDC = EhlersDC(colorRGB1)
    ESP = EhlersSP(colorRGB2)
    ESNR = EhlersSNR(colorRGB3)
    ETV = EhlersTV(colorRGB4)
    
    color1 = "white"
    color2 = "white"
    color3 = "white"
    color4 = "white"
    
    'note Dominate Cycle does not have a color change;
    ' it uses color1 and it will always be white
    
    If colorRGB2 >= 190 And colorRGB2 < 210 Then
        color2 = "LightYellow"
    Else If colorRGB2 >= 200 And colorRGB2 < 220 Then
        color2 = "Yellow"
    Else If colorRGB2 >= 220  Then
        color2 = "Red"
    Else
        color2 = "LightGreen"
    End If
    End If
    End If  

   If colorRGB3 >= 190 And colorRGB3 < 210 Then
        color3 = "LightYellow"
    Else If colorRGB3 >= 200 And colorRGB3 < 220 Then
        color3 = "Yellow"
    Else If colorRGB3 >= 220  Then
        color3 = "Red"
    Else
        color3 = "LightGreen"
    End If
    End If
    End If  
    
    If colorRGB4 >= 190 And colorRGB4 < 210 Then
        color4 = "LightYellow"
    Else If colorRGB4 >= 200 And colorRGB4 < 220 Then
        color4 = "Yellow"
    Else If colorRGB4 >= 220  Then
        color4 = "Red"
    Else
        color4 = "LightGreen"
    End If
    End If
    End If  
    
ColorReport("DominateCycle",CStr(Round(EDC,2)),color1) 
ColorReport("SwingPosition",CStr(Round(ESP,2)), color2)
ColorReport("SigToNoiseR",CStr(Round(ESNR,2)), color3)
ColorReport("TrendVigor",CStr(Round(ETV,2)), color4)

End Sub
_______________________________________________________________________





Function EhlersSNR(ByRef colorRGB)
    Dim price As BarArray, DC As BarArray
    Dim HP As BarArray, SmoothHP As BarArray
    Dim delta As BarArray, gamma As BarArray
    Dim alpha As BarArray, beta As BarArray
    Dim alpha1 As BarArray, MaxAmpl As BarArray
    Dim Num As BarArray, Denom As BarArray
    Dim DomCyc As BarArray, avg1 As BarArray
    Dim sigNR As BarArray, signal As BarArray
    Dim noise As BarArray, width As BarArray
    
    Dim fuzzRGB, lineRGB, maxColorRGB
    Dim N, TScurrentBar, myDate
       
    Dim I As Array, OldI As Array, OlderI As Array
    Dim Q As Array, OldQ As Array, OlderQ As Array
    Dim Real As Array, OldReal As Array, OlderReal As Array
    Dim Imag As Array, OldImag As Array, OlderImag As Array
    Dim Ampl As Array, OldAmpl As Array
    Dim DB As Array, OldDB As Array
    Dim Raster As Array, oldRaster As Array
    Dim aDC As Array, aRange As Array
    Dim color As Array
    
    ReDim (I, 61)
    ReDim (OldI, 61)
    ReDim (OlderI, 61)
    ReDim (Q, 61)
    ReDim (OldQ, 61)
    ReDim (OlderQ, 61)
    ReDim (Real, 61)
    ReDim (OldReal, 61)
    ReDim (OlderReal, 61)
    ReDim (Imag, 61)
    ReDim (OldImag, 61)
    ReDim (OlderImag, 61)
    ReDim (Ampl, 61)
    ReDim (OldAmpl, 61)
    ReDim (DB, 61)
    ReDim (OldDB, 61)
    ReDim (Raster, 51)
    ReDim (oldRaster, 51)
    
    ReDim (aDC,5)
    ReDim (aRange,5)
    ReDim (color,51)
    
    If BarNumber=FirstBar Then
        gamma = 0
        alpha = 0
        beta = 0
        N = 0
        MaxAmpl = 0
        Num = 0
        Denom = 0
        DC = 0
        DomCyc = 0
        alpha1 = 0
        HP = 0
        SmoothHP = 0
        avg1 = 0
        signal = 0
        noise = 0
        sigNR = 0
        width = 0
        For N = 0 To 60
            I[N] = 0
            OldI[N] = 0
            OlderI[N] = 0
            Q[N] = 0
            OldQ[N] = 0
            OlderQ[N]=0
            Real[N] = 0
            OldReal[N] = 0
            OlderReal[N] = 0
            Imag[N] = 0
            OldImag[N] = 0
            OlderImag[N] = 0
            Ampl[N] = 0
            OldAmpl[N] = 0
            DB[N] = 0
            OldDB[N] = 0
        Next
        For N = 0 To 50
            Raster[N] = 0
            oldRaster[N] = 0
            color[N] = 0
        Next
    End If
    
    price = (H+L)/2
    delta = 0.1
    fuzzRGB = 190
    lineRGB = 255
    TScurrentBar = CurrentBar + 1
    myDate = FormatDateTime(Date)
       
    I = GValue401
    OldI = GValue402
    OlderI = GValue403
    Q = GValue404
    OldQ = GValue405
    OlderQ = GValue406
    Real = GValue407
    OldReal = GValue408
    OlderReal = GValue409
    Imag = GValue410
    OldImag = GValue411
    OlderImag = GValue412
    Ampl = GValue413
    OldAmpl = GValue414
    DB = GValue415
    OldDB = GValue416
    Raster = Gvalue417
    oldRaster = Gvalue418

    alpha1 = (1 - Sin(DegToRad(360/30))) / Cos(DegToRad(360/30))
    HP = .5*(1 + alpha1)*(price - price[1]) + alpha1*HP[1]
    SmoothHP = (HP + 2*HP[1] + 3*HP[2] + 3*HP[3] + 2*HP[4] + HP[5]) / 12
    If TScurrentBar < 7 Then SmoothHP = price - price[1]
    If TScurrentBar = 1 Then SmoothHP = 0
    delta = -.015*(TScurrentBar) + .5
    If delta < .1 Then delta = .1
    
If TScurrentBar > 12  Then  'begin condition A
    For N = 12 To 60
        beta = Cos(DegToRad(720 / N))
        gamma = 1 / Cos(DegToRad(1440 * delta / N))
        alpha = gamma - Sqr(gamma * gamma - 1)
        Q[N] = (.5*N / 6.28318)*(SmoothHP - SmoothHP[1])
        I[N] = SmoothHP
        Real[N] = .5*(1 - alpha)*(I[N] - OlderI[N]) + beta*(1 + alpha)*OldReal[N] - alpha*OlderReal[N]
        Imag[N] = .5*(1 - alpha)*(Q[N] - OlderQ[N]) + beta*(1 + alpha)*OldImag[N] - alpha*OlderImag[N]
        Ampl[N] = (Real[N]*Real[N] + Imag[N]*Imag[N])
    Next

    For N = 12 To 60
        OlderI[N] = OldI[N]
        OldI[N] = I[N]
        OlderQ[N] = OldQ[N]
        OldQ[N] = Q[N]
        OlderReal[N] = OldReal[N]
        OldReal[N] = Real[N]
        OlderImag[N] = OldImag[N]
        OldImag[N] = Imag[N]
        OldAmpl[N] = Ampl[N]
        OldDB[N] = DB[N]
    Next
    
    For N = 1 To 50 
        oldRaster[N] = Raster[N]
    Next
    
    MaxAmpl = Ampl[12]
    
    For N = 12 To 60
        If Ampl[N] > MaxAmpl Then MaxAmpl = Ampl[N]
    Next
    
    For N = 12 To 60
        If MaxAmpl <> 0 And (Ampl[N] / MaxAmpl) > 0 Then
            DB[N] = -10 * Log(0.01 / (1 - 0.99 * Ampl[N] / MaxAmpl)) / Log(10)
        End If
        DB[N] = .33*DB[N] + .67*OldDB[N]
        If DB[N] > 20 Then DB[N] = 20
    Next
    
    Num = 0
    Denom = 0
    
    For N = 12 To 60
        If DB[N] <= 6 Then
            Num = Num + N*(20 - DB[N])
            Denom = Denom + (20 - DB[N])
        End If
        If Denom <> 0 Then DC = .5*Num / Denom
    Next   
    For N = 0 To 4
        aDC[N] = DC[N]
    Next
    DomCyc = Median(aDC)
    If DomCyc < 6 Then DomCyc = 6
    
    avg1 = 0.1 * price + 0.9 * avg1[1] 
    If avg1 <> 0 And MaxAmpl > 0 Then signal = 0.2* Sqr(MaxAmpl) + 0.9 * signal[1] 
    
    For N = 0 To 4
        aRange[N] = H[N]-L[N]
    Next 
       
    If avg1 <> 0 And TScurrentBar > 5 Then noise = 0.1 * Median(aRange) + 0.9 * noise[1] 
    If signal <> 0 And noise <> 0 Then sigNR = 20 * Log(signal / noise) / Log(10) + 3.5
    If sigNR < 1 Then sigNR = 0
    If sigNR > 11 Then sigNR = 10
    sigNR = 0.1 * sigNR
    width = -0.4 * sigNR + 0.2
    If sigNR > 0.5 Then width = 0
    
    EhlersSNR = (10*sigNR+1) 
         
    For N = 1 To 50 
        Raster[N] = 20 
        If width > 0 Then
            If N < Round(50*sigNR,0) Then 
                Raster[N] = 0.5*(  ( ( (20*sigNR - 0.4*N) / width) ^ 0.8 ) + oldRaster[N]  ) 
            End If
            If N > Round(50*sigNR, 0) And (0.4*N - 20*sigNR) / width > 1 Then 
                Raster[N] = 0.5*(  (  ( (-20*sigNR + .4*N)/width) ^ 0.8 ) + oldRaster[N]  ) 
            end if
        End If 
        If N = Round(50*sigNR,0) Then Raster[N] = 0 + 0.5*oldRaster[N] 
        If Raster[N] < 0 Then Raster[N] = 0
        If Raster[N] > 20 Then Raster[N] = 20
        If sigNR > 0.5 Then Raster[N] = 20  
    Next
     
 For N = 1 To 50 
    If Raster[N] <= 10 Then 
        color[N] = lineRGB + Raster[N]*(fuzzRGB - lineRGB) / 10
    End If
    If Raster[N] > 10 Then 
        color[N] = fuzzRGB*(2 - Raster[N] / 10)
    End If
    If color[N] > maxColorRGB Then maxColorRGB = color[N]
Next


colorRGB = maxColorRGB
  
End If  'end condition A  
 
    GValue401 = I
    GValue402 = OldI
    GValue403 = OlderI
    GValue404 = Q
    GValue405 = OldQ
    GValue406 = OlderQ
    GValue407 = Real
    GValue408 = OldReal
    GValue409 = OlderReal
    GValue410 = Imag
    GValue411 = OldImag
    GValue412 = OlderImag
    GValue413 = Ampl
    GValue414 = OldAmpl
    GValue415 = DB
    GValue416 = OldDB
    Gvalue417 = Raster
    Gvalue418 = oldRaster

End Function
_______________________________________________________________________________________


sub EhlersSigNoise()
Dim colorRGB
Dim ESNR As BarArray
Dim myDate
myDate = FormatDateTime(Date)
ESNR = EhlersSNR(colorRGB)
plot1(ESNR)
End Sub

_______________________________________________________________________________________


--Richard Denning
richard.denning@earthlink.net
for TraderStudio, www.TradersStudio.com
GO BACK

TRADE IDEAS: FADING THE MARKET

"With globalization, the big [countries] don't eat the small; the fast eat the slow." Thomas L. Friedman (Op-Ed column, The New York Times, February 2, 2001)
Friedman's observation easily applies to traders. For this month's Traders' Tip, we've provided a strategy that uses speed to uncover a backtested and winning advantage in this volatile market. It's based on the Trade Ideas inventory of alerts and filters, and it's backtested with trading rules modeled in The OddsMaker.

This strategy fades certain movements to take advantage of our market view that today's markets are -- and will continue to be -- very volatility. Our hypothesis, given this view of the market, states that stocks moving up at least 75 cents in the last minute tend to be lower over the next 15 minutes. The idea is to put short offers out at the time of the alert.

Please note: If certain categories of stocks are excluded from short sales by the government, simply create a short sell exclusion list.

A video describing how to edit symbol lists appears here: https://www.trade-ideas.com/VideoHelp/Menu.html?video=Trade-Ideas%20Pro:%20Symbol%20List%20Editor This strategy also appears on the Trade Ideas blog at https://marketmovers.blogspot.com/.

FIGURE 12: TRADE IDEAS. Here is the Trade Ideas PRO strategy configuration for the strategy named "Overextended up move."

Description: "Over Extended Up Move"

Provided by: Trade Ideas (copyright © Trade Ideas LLC 2008). All
rights reserved. This sample Trade Ideas strategy and its configuration
are for educational purposes only and may be modified to further reflect
a trading plan. Remember that these set-ups are sketches meant to give an
idea how to model a trading plan. Use this "as is" or modify it as many
others do. Know, however, that Trade-Ideas.com and all individuals affiliated
with this site assume no responsibilities for trading and investment results.
The indicators, alerts and all other features are for research purposes only
and should not be construed as investment advice.





Copy the following string directly into Trade Ideas PRO using the "Collaborate"
feature (right-click in any strategy window): 



https://www.trade-ideas.com/View.php?O=20000000000000000000000000000000000000000000000000000000
_1D_0&QRUN=0.75&MaxPrice=300&MaxSpread=5&MinDNbbo=0.1&MinPrice=10&MinRV=3&MinVol=500000&WN=Over+Extended+Up+Move


where one alert and six filters are used with the following specific settings:
Backtest this strategy using The OddsMaker with the trade rules shown in Figure 13. The results (last backtested for the period of 9/1/2008 to 9/19/2008) are shown in Figure 14.

FIGURE 13: TRADE IDEAS, BACKTESTING. The trade rules for the strategy are shown here. You can use the The OddsMaker facility in Trade Ideas to backtest the strategy.

FIGURE 14: TRADE IDEAS, BACKTEST RESULTS. Here are sample results from backtesting the "Overextended Up Move" strategy. Results shown here are for the period 9/1/2008 to 9/19/2008.

The Trade Ideas manual at https://www.trade-ideas.com/OddsMaker/Help.html can help you understand these backtest results from The OddsMaker component of our software.

--Dan Mirkin
Trade Ideas, LLC
www.trade-ideas.com, dan@trade-ideas.com
GO BACK

VT TRADER: GUPPY MULTIPLE MOVING AVERAGE (GMMA)

For this month's Traders' Tip, we're revisiting two articles by Daryl Guppy and Chen Jing titled "True Price Value" and "Parallel Listings And True Price Value" from the April 2008 and May 2008 issues of STOCKS & COMMODITIES, respectively.

In those two articles, Guppy and Jing discuss the role that psychological trading behavior plays in the relationship between price and value (and the trend patterns it creates) using examples from the Chinese and Hong Kong markets.

The Guppy multiple moving average (GMMA) is used for their market trend analysis. We'll be offering the GMMA indicator for download in our user forums. The VT Trader code and instructions for creating the GMMA indicator are as follows:

The Guppy Multiple Moving Average (GMMA) Indicator

1. Navigator Window>Tools>Indicator Builder>[New] button 2. In the Indicator Bookmark, type the following text for each field:
Name: TASC TASC - 11/2008 - Guppy Multiple Moving Average (GMMA)
Short Name: vt_GMMA
Label Mask: 11/2008 - Guppy Multiple Moving Average (GMMA)
Placement: Price Frame
Inspect Alias: Guppy MMA
3. In the Input Bookmark, create the following variables:
[New] button... Name: MaPrice , Display Name: GMMA Price , Type: price , Default: close
[New] button... Name: MaType , Display Name: GMMA MA Type , Type: MA Type, Default: Exponential
4. In the Output Bookmark, create the following variables:
[New] button...
Var Name: ShortMA1      
Name: (ShortMA1)
Line Color: blue
Line Width: thin
Line Type: solid


[New] button...
Var Name: ShortMA2      
Name: (ShortMA2)
Line Color: blue
Line Width: thin
Line Type: solid


[New] button...
Var Name: ShortMA3      
Name: (ShortMA3)
Line Color: blue
Line Width: thin
Line Type: solid


[New] button...
Var Name: ShortMA4      
Name: (ShortMA4)
Line Color: blue
Line Width: thin
Line Type: solid


[New] button...
Var Name: ShortMA5      
Name: (ShortMA5)
Line Color: blue
Line Width: thin
Line Type: solid


[New] button...
Var Name: ShortMA6      
Name: (ShortMA6)
Line Color: blue
Line Width: thi
Line Type: solid


[New] button...
Var Name: LongMA1       
Name: (LongMA1)
Line Color: red
Line Width: thin
Line Type: solid


[New] button...
Var Name: LongMA2       
Name: (LongMA2)
Line Color: red
Line Width: thin
Line Type: solid


[New] button...
Var Name: LongMA3       
Name: (LongMA3)
Line Color: red
Line Width: thin
Line Type: solid


[New] button...
Var Name: LongMA4       
Name: (LongMA4)
Line Color: red
Line Width: thin
Line Type: solid


[New] button...
Var Name: LongMA5       
Name: (LongMA5)
Line Color: red
Line Width: thin
Line Type: solid


[New] button...
Var Name: LongMA6       
Name: (LongMA6)
Line Color: red
Line Width: thin
Line Type: solid
5. In the Formula Bookmark, copy and paste the following formula:
{Provided By: Visual Trading Systems, LLC & Capital Market Services, LLC (c) Copyright 2008}
{Description: Guppy Multiple Moving Average (GMMA)}
{Notes: T.A.S.C., April 2008 "Similar but Different, True Price Value" by Daryl Guppy and Chen Jing}
{Notes: T.A.S.C., May 2008 "Parallel Listings and True Price Value" by Daryl Guppy and Chen Jing}
{vt_GMMA Version 1.0}

{Short-Term Moving Averages}

ShortMA1:= mov(MaPrice,3,MaType);
ShortMA2:= mov(MaPrice,5,MaType);
ShortMA3:= mov(MaPrice,8,MaType);
ShortMA4:= mov(MaPrice,10,MaType);
ShortMA5:= mov(MaPrice,12,MaType);
ShortMA6:= mov(MaPrice,15,MaType);

{Long-Term Moving Averages}


LongMA1:= mov(MaPrice,30,MaType);
LongMA2:= mov(MaPrice,35,MaType);
LongMA3:= mov(MaPrice,40,MaType);
LongMA4:= mov(MaPrice,45,MaType);
LongMA5:= mov(MaPrice,50,MaType);
LongMA6:= mov(MaPrice,60,MaType);
6. Click the "Save" icon to finish building the GMMA indicator.
FIGURE 15: VT TRADER, GUPPY MULTIPLE MOVING AVERAGE. Here, the GMMA is attached to a EUR/USD daily candle chart.

To attach the indicator to a chart, activate the chart window's contextual menu and select "Add Indicator." Select "Tasc - 11/2008 -- Guppy Multiple Moving Average (GMMA)" from the indicator list and click Add. A sample chart is shown in Figure 15.
To learn more about VT Trader, visit www.cmsfx.com.

--Chris Skidmore
Visual Trading Systems, LLC (courtesy of CMS Forex)
(866) 51-CMSFX, trading@cmsfx.com
www.cmsfx.com
GO BACK

Return to November 2008 Contents

Originally published in the November 2008 issue of Technical Analysis of STOCKS & COMMODITIES magazine. All rights reserved. © Copyright 2008, Technical Analysis, Inc.