Syntax
public UCI(DataSeries ds, int period, int volaperiod, string description)
public static UCI Series(DataSeries ds, int period, int volaper)
Parameter Description
ds |
Source Series, typically Close |
period |
Indicator period (per the article, Minor cycle = 25, Secondary cycle = 50, or Intermediate cycle = 100)
|
volaperiod |
Period for Volatility calculation (50 suggested) |
Description
Universal Cycle Index (UCI) comes from the May 2005 issue of
Stocks & Commodities magazine by Stuart Belknap, PhD: "The UCI is nothing more than a normalized Moving Average Converging/Diverging (MACD) indicator."
Note: UCI employs the EMA of the half period, and therefore you should allow at least twice period for UCI to stabilize.
Example
Based on Version 4 ChartScript "Universal Cycle Index System (SAC May 2005)
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using TASCIndicators;
namespace WealthLab.Strategies
{
public class MyStrategy : WealthScript
{
protected override void Execute()
{
const int DVS_PER = 50; // Volatility Period
const int CYC_PER = 25; // Uni. Cycle Period
DataSeries hDVS = DVS.Series( Close, DVS_PER );
DataSeries hUCI = UCI.Series( Close, CYC_PER, DVS_PER );
/* Plotting */
ChartPane uciPane = CreatePane(40, true, true);
PlotSeries(uciPane, hUCI, Color.Red, LineStyle.Solid, 2);
DrawHorzLine(uciPane, 50, Color.Black, LineStyle.Dotted, 1);
DrawHorzLine(uciPane, -50, Color.Black, LineStyle.Dotted, 1);
ChartPane dvsPane = CreatePane(40, true, true);
PlotSeries(dvsPane, hDVS, Color.Blue, LineStyle.Solid, 2);
/* Trading System */
int startBar = (int)Math.Round( Math.Max( 2 * DVS_PER, 1.5 * CYC_PER ) );
if( startBar >= Bars.Count )
DrawLabel(PricePane, "More bars required", Color.Red );
double Stp = 0d;
for(int bar = startBar; bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
Position p = LastPosition;
if( p.PositionType == PositionType.Long )
{
Stp = p.EntryPrice * ( 1 - hDVS[bar]/100 );
if( Close[bar] < Stp || CrossUnder(bar, hUCI, 50 ) )
{
SellAtMarket(bar + 1, p, "1, Reverse");
ShortAtMarket(bar + 1, "S, Reverse");
}
}
else
{
Stp = p.EntryPrice * ( 1 + hDVS[bar]/100 );
if( Close[bar] > Stp || CrossOver(bar, hUCI, -50 ) )
{
CoverAtMarket(bar + 1, p, "2, Reverse");
BuyAtMarket(bar + 1, "L, Reverse");
}
}
DrawCircle(PricePane, 4, bar, Stp, Color.Maroon, Color.Transparent, LineStyle.Solid, 1, true);
}
else if( CrossOver(bar, hUCI, -50) )
BuyAtMarket(bar + 1, "L");
else if( CrossUnder(bar, hUCI, 50) )
ShortAtMarket(bar + 1, "S");
}
}
}
}