NinjaScript Little Helpers Code Share - Snippets/UserDefinedMethods - NinjaTrader Programming | futures io social day trading
futures io futures trading


NinjaScript Little Helpers Code Share - Snippets/UserDefinedMethods
Updated: Views / Replies:3,692 / 34
Created: by gregid Attachments:3

Welcome to futures io.

(If you already have an account, login at the top of the page)

futures io is the largest futures trading community on the planet, with over 90,000 members. At futures io, our goal has always been and always will be to create a friendly, positive, forward-thinking community where members can openly share and discuss everything the world of trading has to offer. The community is one of the friendliest you will find on any subject, with members going out of their way to help others. Some of the primary differences between futures io and other trading sites revolve around the standards of our community. Those standards include a code of conduct for our members, as well as extremely high standards that govern which partners we do business with, and which products or services we recommend to our members.

At futures io, our focus is on quality education. No hype, gimmicks, or secret sauce. The truth is: trading is hard. To succeed, you need to surround yourself with the right support system, educational content, and trading mentors Ė all of which you can find on futures io, utilizing our social trading environment.

With futures io, you can find honest trading reviews on brokers, trading rooms, indicator packages, trading strategies, and much more. Our trading review process is highly moderated to ensure that only genuine users are allowed, so you donít need to worry about fake reviews.

We are fundamentally different than most other trading sites:
  • We are here to help. Just let us know what you need.
  • We work extremely hard to keep things positive in our community.
  • We do not tolerate rude behavior, trolling, or vendors advertising in posts.
  • We firmly believe in and encourage sharing. The holy grail is within you, we can help you find it.
  • We expect our members to participate and become a part of the community. Help yourself by helping others.

You'll need to register in order to view the content of the threads and start contributing to our community.  It's free and simple.

-- Big Mike, Site Administrator

Reply
 3  
 
Thread Tools Search this Thread
 

NinjaScript Little Helpers Code Share - Snippets/UserDefinedMethods

  #21 (permalink)
Elite Member
San Jose, CA, USA
 
Futures Experience: Intermediate
Platform: NinjaTrader, RCG/Continuum
Favorite Futures: GC,CL
 
Posts: 89 since Dec 2013
Thanks: 14 given, 89 received


gregid View Post
As I was writing g3ChartSpan indicator I needed a way of formatting the TimeSpan to optionally exclude some information if it == 0 and additionally give me some further info like years, months and weeks.

On a similar note, I also needed a way to display time spans in easy to read English, but I was only concerned with Days, Hours, Minutes, and Seconds. Why? In OnTermination() of my strategy, I wanted to print the total runtime since the strategy had started. For example,
 
Code
4/15/15 15:03:55 Strategy 'MyStrat' Terminated at '15:03:55 Wed Apr 15, 2015'
4/15/15 15:03:55 Strategy 'MyStrat' Total runtime '13 hours, 2 minutes, 3 seconds'

I wrote a routine called Duration(), which included several overloads. The main routine just takes 2 DateTime variables,
 
Code
        public static string Duration(DateTime BeginDate, DateTime EndDate)
        {
            if (DateTime.Compare(BeginDate, EndDate) > 0)
                return Duration(EndDate, BeginDate, true);
            else
                return Duration(BeginDate, EndDate, true);
        }

In certain cases I wanted to disable printing of the seconds (regardless if seconds > 0), thus the middle-man overload which takes a 3rd argument as a boolean. WantSeconds=false will set seconds to zero in the timespan structure, which means it won't be included in the returned string. Normally I call the 2-arg version above, except in those cases where I know I don't want to see Seconds, that's when I call this 3-arg version, setting the 3rd argument to false,
 
Code
        public static string Duration(DateTime BeginDate, DateTime EndDate, bool WantSeconds)
        {
            TimeSpan ts = EndDate - BeginDate;

            if (!WantSeconds && (ts.Days + ts.Hours + ts.Minutes) > 0)
                ts = new TimeSpan(ts.Days, ts.Hours, ts.Minutes, 0);

            return Duration(ts);
        }

Finally, here is the routine that formats the returned string. Note how if any one of Days, Hours, Minutes or Seconds is zero, that value won't be included. The exception is if all values are zero, then you'd get the default string "0 seconds".

 
Code
        public static string Duration(TimeSpan ts)
        {
            string Days = String.Format("{0} day{1}", ts.Days, (ts.Days == 1 ? "" : "s"));
            string Hours = String.Format("{0} hour{1}", ts.Hours, (ts.Hours == 1 ? "" : "s"));
            string Minutes = String.Format("{0} minute{1}", ts.Minutes, (ts.Minutes == 1 ? "" : "s"));
            string Seconds = String.Format("{0} second{1}", ts.Seconds, (ts.Seconds == 1 ? "" : "s"));

            string result = null;

            if (ts.Days > 0)
                result += (result == null ? Days : ", " + Days);

            if (ts.Hours > 0)
                result += (result == null ? Hours : ", " + Hours);

            if (ts.Minutes > 0)
                result += (result == null ? Minutes : ", " + Minutes);

            if (ts.Seconds > 0 || result == null)
                result += (result == null ? Seconds : ", " + Seconds);

            return result;
        }


Last edited by bltdavid; April 25th, 2015 at 09:14 PM. Reason: change access from 'private' to 'public static'
Reply With Quote
The following 2 users say Thank You to bltdavid for this post:
 
  #22 (permalink)
Elite Member
San Jose, CA, USA
 
Futures Experience: Intermediate
Platform: NinjaTrader, RCG/Continuum
Favorite Futures: GC,CL
 
Posts: 89 since Dec 2013
Thanks: 14 given, 89 received

Similar to my Duration() routine, I wrote another routine called BriefDuration(), which uses single character suffixes for the days, hours, minutes, and seconds. See attached screenshot showing an example use case.

 
Code
        public static string BriefDuration(DateTime BeginDate, DateTime EndDate)
        {
            if (DateTime.Compare(BeginDate, EndDate) > 0)
                return BriefDuration(EndDate, BeginDate, true);
            else
                return BriefDuration(BeginDate, EndDate, true);
        }

        public static string BriefDuration(DateTime BeginDate, DateTime EndDate, bool WantSeconds)
        {
            TimeSpan ts = EndDate - BeginDate;

            if (!WantSeconds && (ts.Days + ts.Hours + ts.Minutes) > 0)
                ts = new TimeSpan(ts.Days, ts.Hours, ts.Minutes, 0);

            return BriefDuration(ts);
        }

        public static string BriefDuration(TimeSpan ts)
        {
            string result = null;

            if (ts.Days > 0)
                result += String.Format("{0}d", ts.Days);

            if (ts.Hours > 0)
                result += (result == null ? null : " ") + String.Format("{0}h", ts.Hours);

            if (ts.Minutes > 0)
                result += (result == null ? null : " ") + String.Format("{0}m", ts.Minutes);

            if (ts.Seconds > 0 || result == null)
                result += (result == null ? null : " ") + String.Format("{0}s", ts.Seconds);

            return result;
        }

Attached Thumbnails
NinjaScript Little Helpers Code Share - Snippets/UserDefinedMethods-imgdt_20150425_145317.jpg  

Last edited by bltdavid; April 25th, 2015 at 07:08 PM. Reason: change access from 'private' to 'public static'
Reply With Quote
The following user says Thank You to bltdavid for this post:
 
  #23 (permalink)
Elite Member
Wrocław, Poland
 
Futures Experience: Intermediate
Platform: NinjaTrader, Racket
Favorite Futures: Ockham's razor
 
gregid's Avatar
 
Posts: 651 since Aug 2009
Thanks: 321 given, 605 received


Thanks @bltdavid for your contributions to the thread - seeing how many times we all end up reinventing the same stuff makes me wonder what we would all do with the free time on our hands if sharing was just a bit more common

Reply With Quote
 
  #24 (permalink)
Elite Member
San Jose, CA, USA
 
Futures Experience: Intermediate
Platform: NinjaTrader, RCG/Continuum
Favorite Futures: GC,CL
 
Posts: 89 since Dec 2013
Thanks: 14 given, 89 received


gregid View Post
Thanks @bltdavid for your contributions to the thread - seeing how many times we all end up reinventing the same stuff makes me wonder what we would all do with the free time on our hands if sharing was just a bit more common

The problem is sharing code at this low, building-block level (aka, small & useful misc utility routines) is not as common as the high level sharing of entire code units (aka, indicators and strategies). My point is: sharing is happening around here, it's just naturally slanted towards sharing fuller units of code in the forms of indicators & strategies, and perhaps a full class library or two.

But I love the world of well thought-out, well-named small routines.

FWIW, I have found great general purpose code snippets on StackOverflow.com.

But finding general purpose NinjaTrader specific routines has been a (rather laborious) continual exercise of being alert to attachments and uploads, then specifically downloading those files and hunting for any useful looking stand-alone routines.

Another problem is: creating these useful well-named utility classes and/or routines (general purpose or otherwise) is a bit of a fine art, usually practiced only by dedicated and skilled programming professionals. I mean, you probably won't find many cool snippets in some quickie indicator or strategy ... mostly because they're not needed but also because not every code author has the skill or insight or desire to build great low-level standalone routines.

[In summary, I heartily agree with you. These new-fangled terms the kids use such as "refactoring" and "agile" are simply thought exercises that typically center on the reusable-ness and readable-ness of well-named and well-designed routines.]

Reply With Quote
The following 2 users say Thank You to bltdavid for this post:
 
  #25 (permalink)
Elite Member
Monterrey, Mexico
 
Futures Experience: Beginner
Platform: NinjaTrader
Favorite Futures: Treasuries
 
aquarius's Avatar
 
Posts: 22 since Nov 2012
Thanks: 5 given, 69 received

Hope it helps :)


bltdavid View Post
 
Code
  
        public static string BriefDuration(TimeSpan ts)
        {
            string result = null;

            if (ts.Days > 0)
                result += String.Format("{0}d", ts.Days);

            if (ts.Hours > 0)
                result += (result == null ? null : " ") + String.Format("{0}h", ts.Hours);

            if (ts.Minutes > 0)
                result += (result == null ? null : " ") + String.Format("{0}m", ts.Minutes);

            if (ts.Seconds > 0 || result == null)
                result += (result == null ? null : " ") + String.Format("{0}s", ts.Seconds);

            return result;
        }

Please allow me to chime in a little bit ... normally when you modify strings so often, they some how affect performance, mostly because there's garbage collection activity involved from the .Net framework.

A good practice, is to use the StringBuilder class that .net provides instead, i.e.:

 
Code
        public static string BriefDuration(TimeSpan ts)
        {
            StringBuilder result = new StringBuilder();

            if (ts.Days > 0)
                result.AppendFormat("{0}d", ts.Days);

            if (ts.Hours > 0)
                result.Append(" ").AppendFormat("{0}h", ts.Hours);

            if (ts.Minutes > 0)
                result.Append(" ").AppendFormat("{0}m", ts.Minutes);

            if (ts.Seconds > 0)
                result.Append(" ").AppendFormat("{0}s", ts.Seconds);

            return result.ToString().Trim();
        }
Not sure if the code above will give the same results as the one you posted, but hope so ...

here's a link regarding .net strings (also Java's) inmutable property:
c# - Why .NET String is immutable? - Stack Overflow


Reply With Quote
The following user says Thank You to aquarius for this post:
 
  #26 (permalink)
Elite Member
Wrocław, Poland
 
Futures Experience: Intermediate
Platform: NinjaTrader, Racket
Favorite Futures: Ockham's razor
 
gregid's Avatar
 
Posts: 651 since Aug 2009
Thanks: 321 given, 605 received

Enumerable DataSeries

One of my biggest complaints about NinjaTrader is the fact that some basic NT collections/arrays don't implement IEnumerable interface. This unnecesarilly complicates things - it is simply not making use of the existing .NET features.

I am a great fan of flexibility given to the user by LINQ - for an example of LINQ use for arithmetic operations on arrays see the g3VWStdDev indicator. To make use of LINQ you require to operate on enumerable, so until my requests for future @NinjaTrader releases to make that change materialize, I wrote some extension methods to collections/arrays I use most often. Obviously any conversion will always make some impact on the performance but in most cases for most uses it is still worth the flexibility of the newer .NET features (like LINQ)

Here you have:
- ToDoubleArray extensions to DataSeries with 2 overloads - complete DataSeries and a windowed one
- ToEnumerable extensions to IDataSeries with 2 overloads - complete IDataSeries and a windowed one

 
Code
    public static class DataSeriesExtensions
    {
        // Example Use: var test = MyPlot.ToDoubleArray();
        public static double[] ToDoubleArray(this DataSeries series)
        {
            if (series == null) return null;
            int seriesCount = series.Count;
            double[] tempArray = new double[seriesCount];
            for (int i = 0; i < seriesCount; i++)
                tempArray[i] = series[i];
            return tempArray;
        }

        // Example Use: var test = MyPlot.ToDoubleArray(14);
        public static double[] ToDoubleArray(this DataSeries series, int window)
        {
            if (series == null) return null;
            double[] tempArray = new double[window];
            for (int i = 0; i < window; i++)
                tempArray[i] = series[i];
            return tempArray;
        }

        // Example Use: var test = MyPlot.ToEnumerable<double>();
        // The non windowed version doesn't work properly on bar series, eg. Close, Open, etc.)
        // As a workaround use: var test = Close.ToEnumerable<double>(CurrentBar);
        public static IEnumerable<T> ToEnumerable<T>(this IDataSeries series) //where T: IConvertible
        {
            if (series == null) return null;
            int window = series.Count;
            T[] tempArray = new T[window];
            for (int i = 0; i < window; i++)
            {
                tempArray[i] = (T)Convert.ChangeType(series[i], typeof(T));
            }
            return tempArray;
        }

        // Example Use: var test = MyPlot.ToEnumerable<double>(14);
        public static IEnumerable<T> ToEnumerable<T>(this IDataSeries series, int window) //where T: IConvertible
        {
            if (series == null) return null;
            T[] tempArray = new T[window];
            for (int i = 0; i < window; i++)
            {
                tempArray[i] = (T)Convert.ChangeType(series[i], typeof(T));
            }
            return tempArray;
        }
    }
With these extensions getting average of last 10 values of MyPlot dataseries is as simple as:
 
Code
	var myArray = MyPlot.ToDoubleArray(10);
        myArray.Average();


Last edited by gregid; April 27th, 2015 at 05:33 PM.
Reply With Quote
The following 3 users say Thank You to gregid for this post:
 
  #27 (permalink)
Elite Member
Wrocław, Poland
 
Futures Experience: Intermediate
Platform: NinjaTrader, Racket
Favorite Futures: Ockham's razor
 
gregid's Avatar
 
Posts: 651 since Aug 2009
Thanks: 321 given, 605 received

There are situations where my calculations/actions in the indicator or strategy depend on the combination of the parameters. My personal preference of dealing with combinations is to utilise bitwise operators. Let me demonstrate an example for enums. The example is quite naive and could be solved with 4 bools - this is just to show how it works so you can use it for more complex problems.

Let's say I want to give the user a flexible option of what detail of the trade to draw on the chart - including all the combination of the details. I will start with providing an enum:
 
Code
    
    [Flags] //<- crucial for this to work
    public enum DrawOrderDetails
    {
        Entries   = 1 << 0, //decimal:1 binary:0001
        Exits     = 1 << 1, //decimal:2 binary:0010
        Targets   = 1 << 2, //decimal:4 binary:0100
        Stops     = 1 << 3, //decimal:8 binary:1000
        EntriesExits = Entries | Exits,                            //decimal:3 binary:0011
        EntriesExitsTargets = EntriesExits | Targets,              //decimal:7 binary:0111
        EntriesExitsStops = EntriesExits | Stops,                  //decimal:11 binary:1011
        EntriesExitsTargetsStops = EntriesExits | Targets | Stops, //decimal:15 binary:1111
        EntriesTargets = Entries | Targets,                        //decimal:5 binary:0101
        EntriesStops = Entries | Stops,                            //decimal:9 binary:1001
        ExitsTargets = Exits | Targets,                            //decimal:6 binary:0110
        ExitsStops = Exits | Stops,                                //decimal:10 binary:1010
        TargetsStops = Targets | Stops                             //decimal:12 binary:1100
    }
As you can see this provides all the possible combination of objects to be drawn. I provided in the comments the values that will be assigned to individual enum values - you could use any of them if you want eg. decimal or binary but this forces you to be more cautious which values do you assign. Instead in the example for first 4 individual values I used bitwise left shift operator (<<) to provide the right individual values for us. For the combinations bitwise OR (|) to provide the right values.

Now assuming we have eg.
 
Code
private DrawOrderDetails drawDetails;
and would like to check for the condition we can use bitwise operators like this:
 
Code
            if ((DrawOrderDetails.Entries & drawDetails) == DrawOrderDetails.Entries)
            {
                //DrawLine for Entry
            }
But it's not the most readable code you could find.

Instead we could write an extension method to the enum:
 
Code
    public static class EnumExtensions
    {
        public static bool Includes(this DrawOrderDetails testValue, DrawOrderDetails testFor)
        {
            return (testFor & testValue) == testFor;
        }
    }
Now the test for all the conditions are much easier on the eyes:
 
Code
            if (drawDetails.Includes(DrawOrderDetails.Entries))
            {
                //DrawLine for Entry
            }
            if (drawDetails.Includes(DrawOrderDetails.Exits))
            {
                //DrawLine for Exit
            }
            if (drawDetails.Includes(DrawOrderDetails.Targets))
            {
                //DrawLine for Target
            }
            if (drawDetails.Includes(DrawOrderDetails.Stops))
            {
                //DrawLine for Stop
            }
Now for example the Entry line will be drawn for the enum with that includes Entries (in decimals: 1,3,5,7,9,11,15), the same for other conditions


Last edited by gregid; April 27th, 2015 at 04:59 PM.
Reply With Quote
The following 2 users say Thank You to gregid for this post:
 
  #28 (permalink)
Elite Member
San Jose, CA, USA
 
Futures Experience: Intermediate
Platform: NinjaTrader, RCG/Continuum
Favorite Futures: GC,CL
 
Posts: 89 since Dec 2013
Thanks: 14 given, 89 received


gregid View Post
Now the test for all the conditions are much easier on the eyes:
 
Code
            if (drawDetails.Includes(DrawOrderDetails.Entries))
            {
                //DrawLine for Entry
            }
            if (drawDetails.Includes(DrawOrderDetails.Exits))
            {
                //DrawLine for Exit
            }
            if (drawDetails.Includes(DrawOrderDetails.Targets))
            {
                //DrawLine for Target
            }
            if (drawDetails.Includes(DrawOrderDetails.Stops))
            {
                //DrawLine for Stop
            }

Love it, but I think "IsDefined" or "IsEnabled" is a better name than "Includes" ... reads a bit better.

Reply With Quote
 
  #29 (permalink)
Elite Member
Wrocław, Poland
 
Futures Experience: Intermediate
Platform: NinjaTrader, Racket
Favorite Futures: Ockham's razor
 
gregid's Avatar
 
Posts: 651 since Aug 2009
Thanks: 321 given, 605 received


bltdavid View Post
Love it, but I think "IsDefined" or "IsEnabled" is a better name than "Includes" ... reads a bit better.

To each his own

Reply With Quote
The following user says Thank You to gregid for this post:
 
  #30 (permalink)
Elite Member
Birmingham UK
 
Futures Experience: Intermediate
Platform: NinjaTrader
Broker/Data: IG/eSignal
Favorite Futures: Dax
 
ratfink's Avatar
 
Posts: 3,340 since Dec 2012
Thanks: 11,283 given, 7,092 received



bltdavid View Post
Love it, but I think "IsDefined" or "IsEnabled" is a better name than "Includes" ... reads a bit better.

Couldn't disagree more.

With simple 'bool's it should just be:

 
Code
if (entryDetails)
{
    // draw
}
if (exitDetails)
{
    // draw
}
if (targetDetails)
{
    //draw
}
if (stopDetails)
{
    //draw
}

Often in the desire to be with the OO street kids we miss the elephant in the room.


gregid View Post
To each his own

Couldn't disagree more.

That's like saying "It's all about the taking part", when we know it's only ever about the winning.


Cheers both, it's a good sport.

Travel Well
Reply With Quote

Reply



futures io > > > > > NinjaScript Little Helpers Code Share - Snippets/UserDefinedMethods

Thread Tools Search this Thread
Search this Thread:

Advanced Search



Upcoming Webinars and Events (4:30PM ET unless noted)

Jigsaw Trading: TBA

Elite only

FuturesTrader71: TBA

Elite only

NinjaTrader: TBA

Jan 18

RandBots: TBA

Jan 23

GFF Brokers & CME Group: Futures & Bitcoin

Elite only

Adam Grimes: TBA

Elite only

Ran Aroussi: TBA

Elite only
     

Similar Threads
Thread Thread Starter Forum Replies Last Post
vvhg's Little Helpers - Keeping Them In One Place vvhg The Elite Circle 32 January 7th, 2016 11:58 PM
Code TRX Channel for TOS (MT4 Code here) rommark ThinkOrSwim Programming 0 October 1st, 2014 04:55 PM
Code Snippets needed! zeller4 NinjaTrader Programming 11 June 20th, 2011 04:21 PM
code snippets Saroj Feedback and Announcements 1 September 11th, 2009 02:10 PM


All times are GMT -4. The time now is 07:47 PM.

Copyright © 2017 by futures io, s.a., Av Ricardo J. Alfaro, Century Tower, Panama, +507 833-9432, info@futures.io
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.
no new posts
Page generated 2017-12-17 in 0.15 seconds with 20 queries on phoenix via your IP 54.163.209.109