# Source Code

This chapter provides access to source code library for the Cycle Swing Indicator for TradeStation, NinjaTrader, MetaTrader and TradingView. Requires a valid account and login.

# MetaTrader MQ4 - CSI

```C#
//+------------------------------------------------------------------+
//|                                               WTT_CycleSwing.mq4 |
//|                                Copyright 2014- 2017, WhenToTrade |
//|                                      https://www.whentotrade.com |
//|             Book reference: https://www.amazon.com/dp/1974658244 |
//|               License: Attribution 4.0 International (CC BY 4.0) |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014-2017, WhenToTrade"
#property link      "https://www.whentotrade.com"
#property description "WhenToTrade Cycle Swing Indicator (CSI)"
#property description "The CSI is an ultra smooth momentum indicator based on dominant cycles acceleration"
#property description "See book reference: 'Decoding The Hidden Market Rhyhtm - Part 1'"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//--- plot CSI
#property indicator_label1  "CSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- indicator buffers
double CSIBuffer[];
double sourceValues[50];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {

//--- indicator buffers mapping
   SetIndexBuffer(0,CSIBuffer);

//name and label
   //MQL4:
   //IndicatorShortName("WTT CSI");
   //MQL5:
   IndicatorSetString(INDICATOR_SHORTNAME,"WTT CSI");
   
   //MQL4:
   // SetIndexLabel(0,"CSI");
   //MQL5:
   PlotIndexSetString(0,PLOT_LABEL,"CSI");

//Set the starting point of CSI
   //MQL4:
   //SetIndexDrawBegin(0,250);
   //MQL5:
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,250);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   if(rates_total<=200) return(0);

   //--- start variable for calculation of bars
   int start_index=prev_calculated;

   //--- work at the last bar if the indicator values have already been calculated at the previous tick
   if(prev_calculated>0)
      start_index--;

   //--- define indexing direction in arrays
   bool as_series_closes=ArrayGetAsSeries(close);
   bool as_series_buffer=ArrayGetAsSeries(CSIBuffer);
      
   //--- replace indexing direction with direct one if necessary
   if(as_series_closes)
      ArraySetAsSeries(close,false);
   if(as_series_buffer)
      ArraySetAsSeries(CSIBuffer,false);
  
   //--- calculate indicator values
   for(int i=start_index;i<rates_total;i++)
     {
      //--- skip
      if(i<=50) 
        {
         CSIBuffer[i]=0;
         continue;
        }

      //--- prepare data
      for(int p=0;p<50;p++)
         sourceValues[p]=close[i-49+p];

      //--- pre-process dominant cycle momentum
      double thrust1=iWTT_CSI_processor(sourceValues,1);
      double thrust2=iWTT_CSI_processor(sourceValues,10);
      
      //--- get the final cycle acceleration (aka swing)
      CSIBuffer[i]=thrust1-thrust2;

     }

   //--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| www.WhenToTrade.com Cycle Swing Pre-Processor                    |
//+------------------------------------------------------------------+
double Cycle1(int i, double waveThrottle, int cycs)
{
   if (i==0) return 1.0+waveThrottle;
   if (i==1) return 1.0+waveThrottle*5.0;
   if (i==(cycs-1)) return 1.0+waveThrottle;
   if (i==(cycs-2)) return 1.0+waveThrottle*5.0;
   
   return 6.0*waveThrottle+1.0;
}

double Cycle2(int i, double waveThrottle, int cycs)
{ 
   if (i==0) return -2.0*waveThrottle;
   if (i==(cycs-1)) return 0.0;
   if (i==(cycs-2)) return -2.0*waveThrottle;
   
   return -4.0*waveThrottle;
}

double Cycle3(int i, double waveThrottle, int cycs)
{
   if (i==(cycs-1)) return 0.0;
   if (i==(cycs-2)) return 0.0;
   
   return waveThrottle;
}

double iWTT_CSI_processor(const double &raw[], int CycleCount)
  {
   double wtt1=0,wtt2=0,wtt3=0,wtt4=0,wtt5=0,_wtt1=0,_wtt2=0,_wtt3=0,_wtt4=0,_wtt5=0;
   double momentum,acceleration,swing; 
   int cycs=50;
   double waveThrottle=160*CycleCount;
   double currentVal;

   for(int i=0;i<cycs;i++)
   {
      swing=Cycle1(i,waveThrottle,cycs)-wtt4*wtt1-_wtt5*_wtt2;
      if(swing==0) break;
      momentum= Cycle2(i,waveThrottle,cycs);
      _wtt1  = wtt1;
      wtt1   = (momentum-wtt4*wtt2)/swing;
      
      acceleration=Cycle3(i,waveThrottle,cycs);
      _wtt2  = wtt2;
      wtt2   = acceleration/swing;

      currentVal=(raw[i]-_wtt3*_wtt5-wtt3*wtt4)/swing;
      _wtt3  = wtt3;
      wtt3   = currentVal;
      wtt4   = momentum-wtt5*_wtt1;
      _wtt5  = wtt5;
      wtt5   = acceleration;
   }

   return currentVal;
  }
//+------------------------------------------------------------------+
```

# TradeStation EasyLanguage - CSI

```C#
//
// Cycle Swing Indicator (CSI)
// Measuring cycle momentum with no lag. 
// An ultra-smooth, sharp and leading momentum indicator.
// 
// Version 1.0, EasyLanguage for TradeStation
//
// Copyright (C) 2017-2020, Lars von Thienen
// www.whentotrade.com
//
// Book: Decoding The Hidden Market Rhythm - Part 1 (2017)
// Chapter 10: Cycle Swing Indicator
// Link: https://www.amazon.com/dp/1974658244
//
// License: 
// This work is licensed under a Creative Commons Attribution 4.0 International License.
// You are free to share the material in any medium or format and remix, transform, and build upon the material for any purpose, 
// even commercially. You must give appropriate credit to the authors book and website, provide a link to the license, and indicate 
// if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 
//

variables:  
	CSIValue( 0 ),
	thrust1(0), thrust2(0);
	
Arrays: 
	wtt_processed[50](0), cycle1[50](0), cycle2[50](0), cycle3[50](0), sourceValues[50](0) ;
	
method double CSI_PreProcessor(int CycleCount)
variables: int x,
	int p,
	double wtt1, 
	double wtt2, 
	double wtt3, 
	double wtt4, 
	double wtt5, 
	double _wtt1,
	double _wtt2,
	double _wtt3,
	double _wtt4,
	double _wtt5,
	double mom, 
	double acc,
	double swing,
	int cycs,
	double waveThrottle, 
	double ChgRatio;

begin
	waveThrottle=160*CycleCount;
	cycs=50;

	for p=0 to 49 begin
		sourceValues[p]=Close[49-p];
	end;
	
	for x=0 to cycs-1 begin
 	wtt_processed[x]=sourceValues[x];
	end;
	
	If cycs <= 5 then return 0;
	
	cycle1[0]= 1.0+waveThrottle;
	cycle2[0]=-2.0*waveThrottle;
	cycle3[0]=     waveThrottle;
	
	for x=1 to (cycs-2)-1
	begin
		cycle1[x]= 6.0*waveThrottle+1.0;
		cycle2[x]=-4.0*waveThrottle;
		cycle3[x]=     waveThrottle;
	end;
	
	cycle1[1]      = 1.0+waveThrottle*5.0;
	cycle1[cycs-1] = 1.0+waveThrottle;
	cycle1[cycs-2] = 1.0+waveThrottle*5.0;
	cycle2[cycs-2] =-2.0*waveThrottle;
	cycle2[cycs-1] = 0.0;
	cycle3[cycs-2] = 0.0;
	cycle3[cycs-1] = 0.0;
	
	
	for x=0 to cycs-1
	begin
		swing=cycle1[x]-wtt4*wtt1-_wtt5*_wtt2;
		
		if swing=0 then 
		begin
			x=cycs; 
		end
		Else 
		begin
			mom= cycle2[x];
			_wtt1  = wtt1;
			wtt1   = (mom-wtt4*wtt2)/swing;
			cycle2[x]=wtt1;
			
			acc=cycle3[x];
			_wtt2  = wtt2;
			wtt2   = acc/swing;
			cycle3[x]=wtt2;
			
			cycle1[x]=(sourceValues[x]-_wtt3*_wtt5-wtt3*wtt4)/swing;
			_wtt3  = wtt3;
			wtt3   = cycle1[x];
			wtt4   = mom-wtt5*_wtt1;
			_wtt5  = wtt5;
			wtt5   = acc;
		end;
	end;
	
	wtt2 = 0;
	wtt1 = cycle1[cycs-1];
	wtt_processed[cycs-1]=wtt1;
	for x=cycs-2-1 downto 0
	begin
		wtt_processed[x]=cycle1[x]-cycle2[x]*wtt1-cycle3[x]*wtt2;
		wtt2=wtt1;
		wtt1=wtt_processed[x];
	end;
		
	return wtt_processed[49];
end;


thrust1=CSI_PreProcessor(1);
thrust2=CSI_PreProcessor(10);

CSIValue = thrust1-thrust2;

Plot1(CSIValue,"CSI");
```

# NinjaTrader Code - CSI

```C#
// 
// Copyright (C) 2017, WhenToTrade.com
// www.whentotrade.com
// Book: Decoding The Hidden Market Rhythm - Part 1 (2017)
// Chapter 10: Cycle Swing Indicator
// Link: https://www.amazon.com/dp/1974658244
//
// License: 
// This work is licensed under a Creative Commons Attribution 4.0 International License.
// You are free to share the material in any medium or format and remix, transform, and build upon the material for any purpose, 
// even commercially. You must give appropriate credit to the authors book and website, provide a link to the license, and indicate 
// if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 
//

#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion

//This namespace holds Indicators in this folder and is required. Do not change it. 
namespace NinjaTrader.NinjaScript.Indicators
{
	public class WTTCycleSwingIndicator : Indicator
	{
		//used arrays for calculation
		double[] sourceValues= new double[50];
		double[] cycle1= new double[50];
		double[] cycle2= new double[50];
		double[] cycle3= new double[50];
		double[] wtt_processed= new double[50];
		
		protected override void OnStateChange()
		{
			if (State == State.SetDefaults)
			{
				Description				= @"CSI: Smooth and fast momentum indicator based on dominant cycle acceleration. wwww.whentotrade.com";
				Name					= "WTT Cycle Swing Indicator";
				Calculate				= Calculate.OnBarClose;
				IsOverlay				= false;
				DisplayInDataBox			= true;
				DrawOnPricePanel			= true;
				DrawHorizontalGridLines			= true;
				DrawVerticalGridLines			= true;
				PaintPriceMarkers			= true;
				ScaleJustification			= NinjaTrader.Gui.Chart.ScaleJustification.Right;
				IsSuspendedWhileInactive		= true;
				AddPlot(Brushes.Crimson, "CSI");
				AddLine(Brushes.SlateBlue,	0,	NinjaTrader.Custom.Resource.NinjaScriptIndicatorZeroLine);
			}
			else if (State == State.Configure)
			{
			}
			else if (State == State.DataLoaded)
			{
			}
		}

		protected override void OnBarUpdate()
		{
			//Add your custom indicator logic here.
			if (CurrentBar + 1 <= 52) 
			{
				CSI[0]=0;
				return;
			}
			
			 //--- calculate indicator values
			      
			//--- prepare data	
			for(int p=0;p<50;p++)
			   sourceValues[p]=Close[49-p];
	
			 //--- pre-process dominant cycle momentum
			 double thrust1=iWTT_CSI_processor(sourceValues,1);
			 double thrust2=iWTT_CSI_processor(sourceValues,10);

			 //--- get the final cycle acceleration (aka swing)
			 CSI[0]=thrust1-thrust2;
			
		}
		
		//+------------------------------------------------------------------+
		//| www.WhenToTrade.com Cycle Swing Pre-Processor                    |
		//+------------------------------------------------------------------+
	  	double iWTT_CSI_processor(double[] raw, int CycleCount)
	  	{
		   double wtt1=0,wtt2=0,wtt3=0,wtt4=0,wtt5=0,_wtt1=0,_wtt2=0,_wtt3=0,_wtt4=0,_wtt5=0;
		   double momentum,acceleration,swing; 
		   
		   int cycs=50;
		   double waveThrottle=160*CycleCount;

		   for(int i=0;i<cycs;i++) wtt_processed[i]=raw[i];

		   if(cycs <= 5) return 0;

		   cycle1[0]= 1.0+waveThrottle;
		   cycle2[0]=-2.0*waveThrottle;
		   cycle3[0]=     waveThrottle;

		   for(int i=1;i<cycs-2;i++)
		     {
		      cycle1[i]= 6.0*waveThrottle+1.0;
		      cycle2[i]=-4.0*waveThrottle;
		      cycle3[i]=     waveThrottle;
		     }

		   cycle1[1]      = 1.0+waveThrottle*5.0;
		   cycle1[cycs-1] = 1.0+waveThrottle;
		   cycle1[cycs-2] = 1.0+waveThrottle*5.0;
		   cycle2[cycs-2] =-2.0*waveThrottle;
		   cycle2[cycs-1] = 0.0;
		   cycle3[cycs-2] = 0.0;
		   cycle3[cycs-1] = 0.0;

		   for(int i=0;i<cycs;i++)
		     {
		      swing=cycle1[i]-wtt4*wtt1-_wtt5*_wtt2;
		      if(swing==0) break;
		      momentum= cycle2[i];
		      _wtt1  = wtt1;
		      wtt1   = (momentum-wtt4*wtt2)/swing;
		      cycle2[i]=wtt1;

		      acceleration=cycle3[i];
		      _wtt2  = wtt2;
		      wtt2   = acceleration/swing;
		      cycle3[i]=wtt2;

		      cycle1[i]=(raw[i]-_wtt3*_wtt5-wtt3*wtt4)/swing;
		      _wtt3  = wtt3;
		      wtt3   = cycle1[i];
		      wtt4   = momentum-wtt5*_wtt1;
		      _wtt5  = wtt5;
		      wtt5   = acceleration;
		     }

		   wtt2 = 0;
		   wtt1 = cycle1[cycs-1];
		   wtt_processed[cycs-1]=wtt1;
		   for(int i=cycs-2; i>=0; i--)
		     {
		      wtt_processed[i]=cycle1[i]-cycle2[i]*wtt1-cycle3[i]*wtt2;
		      wtt2=wtt1;
		      wtt1=wtt_processed[i];
		     }
		     
		   return wtt_processed[49];

	  	}

		#region Properties

		[Browsable(false)]
		[XmlIgnore]
		public Series<double> CSI
		{
			get { return Values[0]; }
		}
		#endregion

	}
}

#region NinjaScript generated code. Neither change nor remove.

namespace NinjaTrader.NinjaScript.Indicators
{
	public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
	{
		private WTTCycleSwingIndicator[] cacheWTTCycleSwingIndicator;
		public WTTCycleSwingIndicator WTTCycleSwingIndicator()
		{
			return WTTCycleSwingIndicator(Input);
		}

		public WTTCycleSwingIndicator WTTCycleSwingIndicator(ISeries<double> input)
		{
			if (cacheWTTCycleSwingIndicator != null)
				for (int idx = 0; idx < cacheWTTCycleSwingIndicator.Length; idx++)
					if (cacheWTTCycleSwingIndicator[idx] != null &&  cacheWTTCycleSwingIndicator[idx].EqualsInput(input))
						return cacheWTTCycleSwingIndicator[idx];
			return CacheIndicator<WTTCycleSwingIndicator>(new WTTCycleSwingIndicator(), input, ref cacheWTTCycleSwingIndicator);
		}
	}
}

namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
{
	public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
	{
		public Indicators.WTTCycleSwingIndicator WTTCycleSwingIndicator()
		{
			return indicator.WTTCycleSwingIndicator(Input);
		}

		public Indicators.WTTCycleSwingIndicator WTTCycleSwingIndicator(ISeries<double> input )
		{
			return indicator.WTTCycleSwingIndicator(input);
		}
	}
}

namespace NinjaTrader.NinjaScript.Strategies
{
	public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
	{
		public Indicators.WTTCycleSwingIndicator WTTCycleSwingIndicator()
		{
			return indicator.WTTCycleSwingIndicator(Input);
		}

		public Indicators.WTTCycleSwingIndicator WTTCycleSwingIndicator(ISeries<double> input )
		{
			return indicator.WTTCycleSwingIndicator(input);
		}
	}
}

#endregion
```