The code I am trying to convert from TradingView is here:
The same code can be found for ThinkOrSwim here:
Any help is appreciated. I didn't include the "Do Not Touch" section due to character limits.
The code I created is this:
[CODE]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 CyclicSmoothedRSIV2 : Indicator
{
private Series<double> CyclicRSI;
private Series<double> NormalRSI;
private Series<double> Wilders;
private Series<double> Src;
private Series<double> Up;
private Series<double> Down;
private Series<double> Lm_Hist;
private Series<double> DB;
private Series<double> UB;
private Series<double> CautionUp;
private Series<double> CautionDown;
private Series<double> CautionBase;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"// Copyright (C) 2017 CC BY, whentotrade / Lars von Thienen
Source:
Book: Decoding The Hidden Market Rhythm - Part 1: Dynamic Cycles (2017)
Chapter 4: "Fine-tuning technical indicators for more details on the cRSI Indicator
Usage:
You need to derive the dominant cycle as input parameter for the cycle length as described in chapter 4.
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.
Modified by IMakeNoCents";
Name = "CyclicSmoothedRSIV2";
Calculate = Calculate.OnBarClose;
IsOverlay = false;
DisplayInDataBox = true;
DrawOnPricePanel = true;
DrawHorizontalGridLines = true;
DrawVerticalGridLines = true;
PaintPriceMarkers = true;
ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
//Disable this property if your indicator requires custom values that cumulate with each new market data event.
//See Help Guide for additional information.
IsSuspendedWhileInactive = true;
Domcycle = 28;
RSI_Upper = 70;
RSI_Lower = 30;
ShowCyclicMidline = true;
UseFullView = false;
ShowRSImidline = false;
ShowCaution = true;
ShowClouds =true;
AddPlot(Brushes.Aqua, "Lowband");
AddPlot(Brushes.Aqua, "Highband");
AddPlot(Brushes.WhiteSmoke, "CRSI");
AddPlot(new Stroke(Brushes.MediumOrchid, 2), PlotStyle.Dot, "Centerline");
AddPlot(new Stroke(Brushes.DarkGray, 2), PlotStyle.Hash, "Mid");
}
else if (State == State.Configure)
{
}
else if (State == State.DataLoaded)
{
if(ShowRSImidline)
{
Mid[0] = 50;
}
if(UseFullView)
{
AddLine(Brushes.DarkRed, 100, "FullViewUpperLimit");
AddLine(Brushes.LimeGreen, 0, "FullViewLowerLimit");
}
}
}
protected override void OnBarUpdate()
{
Src[0] = Close[0];
CyclicRSI[0] = 0.0;
double cyclelen = Domcycle / 2;
int vibration = 10;
double leveling = 10.0;
int cyclicMemory = Domcycle * 2;
int RSI_Center = 50;
double torque = 2.0 / (vibration + 1);
double phasingLag = (vibration - 1) / 2.0;
double alpha = 1 / cyclelen;
if(CurrentBar == 0)
{
Up[0] = 0.0;
Down[0] = 0.0;
Lm_Hist[0] = 0.0;
NormalRSI[0] = 0.0;
CyclicRSI[0] = 0.0;
DB[0] = 0.0;
UB[0] = 0.0;
}
else
{
Up[0] = alpha * Math.Max(Src[0] - Src[1], 0) + (1 - alpha) * Up[1];
Down[0] = alpha * -Math.Min(Src[0] - Src[1], 0) + (1 - alpha) * Down[1];
}
if(CurrentBar > 0 && Down[0] == 0)
{
NormalRSI[0] = 100;
}
else if(CurrentBar > 0 && Up[0] == 0)
{
NormalRSI[0] = 0;
}
else
{
NormalRSI[0] = 100 - 100 / (1 + Up[0] / Down[0]);
}
if(CurrentBar > 0)
{
CyclicRSI[0] = torque * (2 * NormalRSI[0] - NormalRSI[4]) + (1 - torque) * CyclicRSI[1];
}
double CyclicMax = MAX(CyclicRSI, cyclicMemory - 1)[0];
double CyclicMin = MIN(CyclicRSI, cyclicMemory -1)[0];
if(CurrentBar > 0)
{
Lm_Hist[0] = CyclicRSI[0] > CyclicMax ? CyclicRSI[0] : -CyclicRSI[0] < CyclicMin ? -CyclicRSI[0] : 0;
}
double lmax = -MAX(Lm_Hist, cyclicMemory - 1)[0];
double lmin = -MIN(Lm_Hist, cyclicMemory - 1)[0];
double mstep = (lmax - lmin) / 100;
double aperc = leveling / 100;
for(int i = 0; i < 101; i++)
{
double testvalue = lmin + mstep * i;
double below = 0;
for(int j = 0; j < cyclicMemory; j++)
{
below += (CyclicRSI[j] < testvalue ? 1 : 0);
}
double ratio = below / cyclicMemory;
if(ratio >= aperc)
{
DB[0] = testvalue;
break;
}
else
{
continue;
}
}
for(int i = 0; i < 101; i++)
{
double testvalue = lmax - mstep * i;
double above = 0;
for(int j = 0; j < cyclicMemory; j++)
{
above += (CyclicRSI[j] >= testvalue ? 1 : 0);
}
double ratio = above / cyclicMemory;
if(ratio >= aperc)
{
UB[0] = testvalue;
break;
}
else
{
continue;
}
}
double center = (UB[0] + DB[0]) / 2;
bool downTrend = CyclicRSI[0] < DB[0] ? true : false;
bool upTrend = CyclicRSI[0] > UB[0] ? true : false;
bool crossingDown = CrossBelow(CyclicRSI, UB, 0);
bool crossingUp = CrossAbove(CyclicRSI, DB, 0);
Lowband[0] = DB[0];
Highband[0] = UB[0];
CRSI[0] = CyclicRSI[0];
Centerline[0] = center;
if(ShowCaution)
{
int savedCautionBar = 0;
if(DB[0] <= RSI_Lower && CRSI[0] < DB[0] && UB[0] < (RSI_Upper - ((100 - RSI_Upper) / 2)))
{
CautionUp[0] = 100;
if(CrossAbove(CautionUp, 50, 0))
{
savedCautionBar = CurrentBar;
}
}
else
{
CautionUp.Reset();
}
if(UB[0] >= RSI_Upper && CRSI[0] > UB[0] && DB[0] > (RSI_Lower + (RSI_Lower / 2)))
{
CautionDown[0] = 100;
if(CrossBelow(CautionDown, 50, 0))
{
savedCautionBar = CurrentBar;
}
}
else
{
CautionDown.Reset();
}
if(CautionUp[0] == 100 || CautionDown[0] == 100)
{
CautionBase[0] = 0;
if(CautionUp[0] == 100)
{
Draw.Region(this, "Look for Reversals - Caution", CurrentBar - savedCautionBar + 1, 0, CautionBase, CautionUp, null, Brushes.Goldenrod, 30);
}
if(CautionDown[0] == 100)
{
Draw.Region(this, "Look for Reversals - Caution", CurrentBar - savedCautionBar + 1, 0, CautionBase, CautionDown ,null, Brushes.Goldenrod, 30);
}
}
else
{
CautionBase.Reset();
}
}
if(ShowClouds)
{
int savedCrossOverBar;
}
//END
}
region Properties
[NinjaScriptProperty]
[Range(10, int.MaxValue)]
[Display(Name="Domcycle", Description="Dominant Cycle Length", Order=1, GroupName="Parameters")]
public int Domcycle
{ get; set; }
[NinjaScriptProperty]
[Range(1, int.MaxValue)]
[Display(Name="RSI_Upper", Description="Upper Limit - Normal RSI", Order=2, GroupName="Parameters")]
public int RSI_Upper
{ get; set; }
[NinjaScriptProperty]
[Range(1, int.MaxValue)]
[Display(Name="RSI_Lower", Description="Lower RSI - Normal Limit", Order=3, GroupName="Parameters")]
public int RSI_Lower
{ get; set; }
[NinjaScriptProperty]
[Display(Name="ShowCyclicMidline", Description="Display the average of upper and lower bands", Order=4, GroupName="Parameters")]
public bool ShowCyclicMidline
{ get; set; }
[NinjaScriptProperty]
[Display(Name="UseFullView", Description="Plot lines at 0 and 100 to show full view of indicator", Order=5, GroupName="Parameters")]
public bool UseFullView
{ get; set; }
[NinjaScriptProperty]
[Display(Name="ShowRSImidline", Description="Plot a line at the 50 level of the indicator for reference", Order=6, GroupName="Parameters")]
public bool ShowRSImidline
{ get; set; }
[NinjaScriptProperty]
[Display(Name="ShowCaution", Description="Highlights background when indicator is entering very overbought or oversold territory", Order=7, GroupName="Parameters")]
public bool ShowCaution
{ get; set; }
[NinjaScriptProperty]
[Display(Name="ShowClouds", Description="Highlights area between CRSI and Highband or Lowband if trending above or below them", Order=8, GroupName="Parameters")]
public bool ShowClouds
{ get; set; }
[Browsable(false)]
[XmlIgnore]
public Series<double> Lowband
{
get { return Values[0]; }
}
[Browsable(false)]
[XmlIgnore]
public Series<double> Highband
{
get { return Values[1]; }
}
[Browsable(false)]
[XmlIgnore]
public Series<double> CRSI
{
get { return Values[2]; }
}
// [Browsable(false)]
// [XmlIgnore]
// public Series<double> CautionUp
// {
// get { return Values[3]; }
// }
// [Browsable(false)]
// [XmlIgnore]
// public Series<double> CautionDown
// {
// get { return Values[4]; }
// }
[Browsable(false)]
[XmlIgnore]
public Series<double> Mid
{
get { return Values[3]; }
}
[Browsable(false)]
[XmlIgnore]
public Series<double> Centerline
{
get { return Values[4]; }
}
// [Browsable(false)]
// [XmlIgnore]
// public Series<double> CautionBase
// {
// get { return Values[6]; }
// }
#endregion
}
}
Comment