NexusFi: Find Your Edge


Home Menu

 





Think or Swim indicator converted to Ninjatrader


Discussion in NinjaTrader

Updated
      Top Posters
    1. looks_one caniwi with 12 posts (0 thanks)
    2. looks_two bobwest with 5 posts (3 thanks)
    3. looks_3 nguyen74 with 3 posts (5 thanks)
    4. looks_4 SamirOfSalem with 3 posts (3 thanks)
      Best Posters
    1. looks_one nguyen74 with 1.7 thanks per post
    2. looks_two hedgeplay with 1.5 thanks per post
    3. looks_3 SamirOfSalem with 1 thanks per post
    4. looks_4 bobwest with 0.6 thanks per post
    1. trending_up 5,933 views
    2. thumb_up 16 thanks given
    3. group 6 followers
    1. forum 25 posts
    2. attach_file 5 attachments




 
Search this Thread

Think or Swim indicator converted to Ninjatrader

  #21 (permalink)
 
bobwest's Avatar
 bobwest 
Western Florida
Site Moderator
 
Experience: Advanced
Platform: Sierra Chart
Trading: ES, YM
Frequency: Several times daily
Duration: Minutes
Posts: 8,172 since Jan 2013
Thanks Given: 57,513
Thanks Received: 26,292


caniwi View Post
Hi again,

Is converting these something doable for a non techie guy like me? Is there some online resource I could go to to teach myself?

I have another ToS script here that I'd really like for NT8:- V01.08.2012 Projection Pivots. Maybe there is a conversion somewhere though. If I can't find a conversion I'd be willing to give it a try....


hedgeplay View Post
Hi!

I would post a few screen shots of what you are looking (final screen views of this pivots Indicator).

There is a good chance it has already been coded and if we recognized it can help you find the existing indicator file.

HedgePlay

Agree with @hedgeplay. It is amazingly hard for a programmer to go into some code and just see what it's doing without having some clue given beforehand. Basically, you're seldom going to get any takers if there's not a screenshot and an explanation of what's going on. Also, many indicators are the same across different platforms, so a description or picture will help there as well.

For instance, there are all sorts of pivots out there. If we're talking about regular "floor pivots" or similar calculations, its already been done.

As to teaching yourself, well, a good way to learn to program is to have a project you want to work on... it is doable, but it's not anything like easy, and in this case it's mastering two different languages and then the particular functions that are available in two different platforms. For a non techie guy, I'm afraid you'd need to pretty much become a full techie guy . Sorry.

Bob.

When one door closes, another opens.
-- Cervantes, Don Quixote
Reply With Quote
Thanked by:

Can you help answer these questions
from other members on NexusFi?
Pivot Indicator like the old SwingTemp by Big Mike
NinjaTrader
REcommedations for programming help
Sierra Chart
Cheap historycal L1 data for stocks
Stocks and ETFs
MC PL editor upgrade
MultiCharts
ZombieSqueeze
Platforms and Indicators
 
  #22 (permalink)
 
bobwest's Avatar
 bobwest 
Western Florida
Site Moderator
 
Experience: Advanced
Platform: Sierra Chart
Trading: ES, YM
Frequency: Several times daily
Duration: Minutes
Posts: 8,172 since Jan 2013
Thanks Given: 57,513
Thanks Received: 26,292


caniwi View Post
Hi again,

Is converting these something doable for a non techie guy like me? Is there some online resource I could go to to teach myself?

I have another ToS script here that I'd really like for NT8:- V01.08.2012 Projection Pivots. Maybe there is a conversion somewhere though. If I can't find a conversion I'd be willing to give it a try....

Also, there is thread devoted just to getting free help for creating NT indicators:



However, it is for Elite members only. Also, not every request is answered, since the help is both free and voluntary.

You've been getting free help really for free, because people really do want to help here... and of course you can continue to do so.

---------------

I have said often, and I believe, that a person should not take an Elite membership just to get something like an indicator, or some other single thing. There is a ton of threads that are Elite-only, but the decision to go Elite or not should be made based on someone's experience with the forum and their decision to take part in the full community, not to get something nice as a one-off thing. There is a cost (one-time) because it takes a commitment, for that reason.

On the other hand, most new members either drift away and are not heard from after a while, or decide that it may be worth it and make the decision. (Which you can never be sure is worth it until after you've made it, like any decision.)

Just saying.

Bob.

When one door closes, another opens.
-- Cervantes, Don Quixote
Reply With Quote
  #23 (permalink)
 nguyen74 
Baton Rouge, LA - USA
 
Experience: None
Platform: NinjaTrader, RTrader
Trading: Emini ES, Crude CL
Posts: 61 since Sep 2016
Thanks Given: 24
Thanks Received: 72



SamirOfSalem View Post
If still looking, here's a quick conversion. There's an input towards the end "length1" that doesn't seem to be used, unless I'm missing something. Anyway, have a look and see if results match ToS.

 
Code
namespace NinjaTrader.NinjaScript.Indicators
{
	public class ToS389BuySellVolume : Indicator
	{
        private int spacing;
        private int items2show;
		public override void OnCalculateMinMax()
        {
            // make sure to always start fresh values to calculate new min/max values
            double tmpMin = double.MaxValue;
            double tmpMax = double.MinValue;

            // For performance optimization, only loop through what is viewable on the chart
            for (int index = ChartBars.FromIndex; index <= ChartBars.ToIndex; index++)
            {
                // since using Close[0] is not guaranteed to be in sync
                // retrieve "Close" value at the current viewable range index
                double plotValue = Volumes[0].GetValueAt(index);

                // return min/max of close value
                tmpMin = Math.Min(tmpMin, plotValue);
                tmpMax = Math.Max(tmpMax, plotValue);
            }

            // Finally, set the minimum and maximum Y-Axis values to +/- 50 ticks from the primary close value
            MinValue = tmpMin; // -50 * TickSize;
            MaxValue = tmpMax; // +50 * TickSize; 
        }     
        protected override void OnStateChange()
		{
			if (State == State.SetDefaults)
			{
				Description									= @"NT8 conversion of https://usethinkscript.com/threads/volume-buy-sell-indicator-with-hot-percent-for-thinkorswim.389/";
				Name										= "_ToS389 Buy-Sell Volume";
				Calculate									= Calculate.OnPriceChange;
				IsOverlay									= false;
				DisplayInDataBox							= true;
				DrawOnPricePanel							= false;
				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;
				
                Show30DayAvg			= true;
				ShowTodayVolume			= true;
				ShowPercentOf30DayAvg	= true;
				UnusualVolumePercent	= 200;
				Show30BarAvg			= true;
				ShowCurrentBar			= true;
				ShowPercentOf30BarAvg	= true;
				ShowSellVolumePercent	= true;
				Length					= 20;
				Length1					= 20;
				HotPct					= 100;

				type                    = ToS_389_MovingAverageTypes.SMA;
                position                = TextPosition.TopLeft;

				AddPlot(new Stroke(Brushes.Green, 5), PlotStyle.Bar, "BuyVol");
				AddPlot(new Stroke(Brushes.Red, 2), PlotStyle.Bar, "SellVol");
				AddPlot(new Stroke(Brushes.Gray, 2), PlotStyle.Bar, "TV");
				AddPlot(new Stroke(Brushes.LightGray, 1), PlotStyle.Line, "Vol Avg");
				AddPlot(new Stroke(Brushes.Cyan, 2), PlotStyle.TriangleUp, "HV" );

			}
			else if (State == State.Configure)
			{
        		AddDataSeries(BarsPeriodType.Day, 1);
			}
		}

		protected override void OnBarUpdate()
		{
            if (BarsInProgress == 1) return;
            
            //Add your custom indicator logic here.
		    double O = Open[0];
		    double H = High[0];
		    double C = Close[0];
		    double L = Low[0];
		    double V = Volume[0];
		    double buying = V*(C-L)/(H-L);
		    double selling = V*(H-C)/(H-L);		
		
			SellVol[0] = selling;
			TV[0] = Volume[0];
			BuyVol[0] = buying;
            VolAvg[0] = SMA(Volume, Length)[0];
            double ma = (type == ToS_389_MovingAverageTypes.SMA) ? SMA(Volume, Length)[0] : EMA(Volume, Length)[0]; 
            Hv[0] = (100 * ((Volume[0] / ma) - 1) >= HotPct) ? ma : Double.NaN;
            double volLast30DayAvg = (CurrentBars[1] <= 30) ? 0 : (Volumes[1][1] + Volumes[1][2] + Volumes[1][3] + Volumes[1][4] + Volumes[1][5] + Volumes[1][6] + Volumes[1][7] + Volumes[1][8] + Volumes[1][9] + Volumes[1][10] + Volumes[1][11] + Volumes[1][12] + Volumes[1][13] + Volumes[1][14] + Volumes[1][15] + Volumes[1][16] + Volumes[1][17] + Volumes[1][18] + Volumes[1][19] + Volumes[1][20] + Volumes[1][21] + Volumes[1][22] + Volumes[1][23] + Volumes[1][24] + Volumes[1][25] + Volumes[1][26] + Volumes[1][27] + Volumes[1][28] + Volumes[1][29] + Volumes[1][30]) / 30;
            double today = (CurrentBars[1] <= 30) ? 0 : Volumes[1][0]; 
            double percentOf30Day = Math.Round((today / volLast30DayAvg) * 100, 0);
            double avg30Bars = (CurrentBar <= 30) ? 0 : (Volume[1] + Volume[2] + Volume[3] + Volume[4] + Volume[5] + Volume[6] + Volume[7] + Volume[8] + Volume[9] + Volume[10] + Volume[11] + Volume[12] + Volume[13] + Volume[14] + Volume[15] + Volume[16] + Volume[17] + Volume[18] + Volume[19] + Volume[20] + Volume[21] + Volume[22] + Volume[23] + Volume[24] + Volume[25] + Volume[26] + Volume[27] + Volume[28] + Volume[29] + Volume[30]) / 30;
            double curVolume = Volume[0];
            double percentOf30Bar = Math.Round((curVolume / avg30Bars) * 100, 0);
            double SellVolPercent = Math.Round((selling / Volume[0]) * 100, 0); 

            items2show = countInputFields();
            spacing = 0;
            if (position == TextPosition.BottomLeft || position == TextPosition.BottomRight)
                spacing = 20 * (items2show-1);

            TextFixed tf;

            if (Show30DayAvg) {
                tf = Draw.TextFixed(this, "Avg 30 Days", String.Format("Avg 30 Days: {0:n0}", Math.Round(volLast30DayAvg, 0)), position);
                tf.AreaBrush = Brushes.LightGray;
                formatTextBox(tf); }

            if (ShowTodayVolume) {
                tf = Draw.TextFixed(this, "Today", String.Format("Today: {0:n0}", today), position);
                if (percentOf30Day >= UnusualVolumePercent) tf.AreaBrush = Brushes.Green; else if (percentOf30Day >= 100)  tf.AreaBrush = Brushes.Orange; else tf.AreaBrush = Brushes.LightGray;
                formatTextBox(tf); }

            if (ShowPercentOf30DayAvg) {
                tf = Draw.TextFixed(this, "Percent of 30 Day", percentOf30Day + "%", position);
                if (percentOf30Day >= UnusualVolumePercent) tf.AreaBrush = Brushes.Green; else if (percentOf30Day >= 100) tf.AreaBrush = Brushes.Orange; else tf.AreaBrush = Brushes.White; 
                formatTextBox(tf); }

			if (ShowCurrentBar) {
                tf = Draw.TextFixed(this, "Cur Bar", String.Format("Cur Bar: {0:n0}", curVolume), position);
				if (percentOf30Bar >= UnusualVolumePercent) tf.AreaBrush = Brushes.Green; else if (percentOf30Bar >= 100) tf.AreaBrush = Brushes.Orange; else tf.AreaBrush = Brushes.LightGray;
                formatTextBox(tf); }

			if (ShowPercentOf30BarAvg) {
                tf = Draw.TextFixed(this, "Percent of 30 Bar", percentOf30Bar + "%", position);
				if (percentOf30Bar >= UnusualVolumePercent) tf.AreaBrush = Brushes.Green; else if (percentOf30Bar >= 100) tf.AreaBrush = Brushes.Orange; else tf.AreaBrush = Brushes.White;
                formatTextBox(tf);  }

			if (ShowPercentOf30BarAvg) {
                tf = Draw.TextFixed(this, "Cur Bar Sell %", "Cur Bar Sell %: " + SellVolPercent + "%", position);
				if (SellVolPercent > 51) tf.AreaBrush = Brushes.Red; else if (SellVolPercent < 49) tf.AreaBrush = Brushes.Green; else tf.AreaBrush = Brushes.Orange;
                formatTextBox(tf); }

			return;
		}
		
		void formatTextBox(TextFixed tf)
        {
            if (tf.TextPosition == TextPosition.Center) tf.TextPosition = TextPosition.TopLeft;
            tf.Font = ChartControl.Properties.LabelFont;
            tf.TextBrush = ChartControl.Properties.ChartText;
            tf.TextBrush = Brushes.Black;
            tf.YPixelOffset = spacing;
            spacing += -20;
        }
        int countInputFields()
        {
            items2show = 0 +
            Convert.ToInt32(Show30BarAvg) + 
            Convert.ToInt32(Show30DayAvg) + 
            Convert.ToInt32(ShowPercentOf30BarAvg) + 
            Convert.ToInt32(ShowPercentOf30DayAvg) + 
            Convert.ToInt32(ShowSellVolumePercent) + 
            Convert.ToInt32(ShowTodayVolume);
            return items2show;
        }

        #region Properties
		[NinjaScriptProperty]
		[Display(Name="Show30DayAvg", Order=1, GroupName="Parameters")]
		public bool Show30DayAvg
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="ShowTodayVolume", Order=2, GroupName="Parameters")]
		public bool ShowTodayVolume
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="ShowPercentOf30DayAvg", Order=3, GroupName="Parameters")]
		public bool ShowPercentOf30DayAvg
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="UnusualVolumePercent", Order=4, GroupName="Parameters")]
		public int UnusualVolumePercent
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="Show30BarAvg", Order=5, GroupName="Parameters")]
		public bool Show30BarAvg
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="ShowCurrentBar", Order=6, GroupName="Parameters")]
		public bool ShowCurrentBar
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="ShowPercentOf30BarAvg", Order=7, GroupName="Parameters")]
		public bool ShowPercentOf30BarAvg
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="ShowSellVolumePercent", Order=8, GroupName="Parameters")]
		public bool ShowSellVolumePercent
		{ get; set; }

		[NinjaScriptProperty]
		[Range(1, int.MaxValue)]
		[Display(Name="Length", Order=9, GroupName="Parameters")]
		public int Length
		{ get; set; }

		[NinjaScriptProperty]
		[Range(1, int.MaxValue)]
		[Display(Name="Length1", Order=10, GroupName="Parameters")]
		public int Length1
		{ get; set; }

		[NinjaScriptProperty]
		[Range(1, double.MaxValue)]
		[Display(Name="HotPct", Order=11, GroupName="Parameters")]
		public double HotPct
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name = "Moving Averate Type", Order = 11, GroupName = "Parameters")]
		public ToS_389_MovingAverageTypes type
		{ get; set; }

        [NinjaScriptProperty]
        [Display(Name = "Label Positioning", Order = 21, GroupName = "Parameters")]
        public TextPosition position
        { get; set; }


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

		[Browsable(false)]
		[XmlIgnore]
		public Series<double> TV
		{
			get { return Values[1]; }
		}

		[Browsable(false)]
		[XmlIgnore]
		public Series<double> BuyVol
		{
			get { return Values[2]; }
		}

		[Browsable(false)]
		[XmlIgnore]
		public Series<double> VolAvg
		{
			get { return Values[3]; }
		}

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

	}
}

@SamirOfSalem First, nice work on the conversion! Second, the plot properties seem to be switched around. The Sell plot properties should be the Total Volume (TV). The Total Volume plot properties should be the Buy. The Buy plot properties should be the Sell. If you could double check that and fix it, that would be great.

Visit my NexusFi Trade Journal Reply With Quote
Thanked by:
  #24 (permalink)
 SamirOfSalem   is a Vendor
 
Posts: 74 since Jan 2020
Thanks Given: 23
Thanks Received: 44


nguyen74 View Post
@SamirOfSalem First, nice work on the conversion! Second, the plot properties seem to be switched around. The Sell plot properties should be the Total Volume (TV). The Total Volume plot properties should be the Buy. The Buy plot properties should be the Sell. If you could double check that and fix it, that would be great.

Good that you mention it. Maybe now's a good time to point out this was more of a "translation" than a conversion. I didn't have ToS or decent volume data to check against. And no error-trapping either.

About the swapped-around plots, the AddPlot statements were re-arranged to control what prints above what. But since the Values[] arrays are named at the very bottom, the calculations themselves shouldn't be switched around. Or at least I hope so

Reply With Quote
  #25 (permalink)
 nguyen74 
Baton Rouge, LA - USA
 
Experience: None
Platform: NinjaTrader, RTrader
Trading: Emini ES, Crude CL
Posts: 61 since Sep 2016
Thanks Given: 24
Thanks Received: 72


SamirOfSalem View Post
If still looking, here's a quick conversion. There's an input towards the end "length1" that doesn't seem to be used, unless I'm missing something. Anyway, have a look and see if results match ToS.

The person who wrote the thinkscript code already used "length" for the VolAvg calculation. The "length1" was meant for the hiVolume calculation and should have been used for that purpose. I think that is the mistake on the person who created the TOS indicator. In this case, since only one length is used, both the VolAvg and the hiVolume is based on the same range.

Visit my NexusFi Trade Journal Reply With Quote
  #26 (permalink)
caniwi
Alberta, Canada
 
Posts: 14 since Aug 2021
Thanks Given: 19
Thanks Received: 5





Here's a couple of screenshots of what this script produces.

Basically draws pivot points & the trendlines resulting from these pivots.

I have found built in NT8 indicators ("Swung" & "Trendlines") that when running both result in something similar, but not as "clean" as this one.

Maybe it's already out there, but I couldn't find it.

Thanks in advance....

Bruce

Origin is a ToS study: V01.08.2012 Projection Pivots

Reply With Quote




Last Updated on September 6, 2021


© 2024 NexusFi™, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Privacy Policy - Downloads - Top
no new posts