NexusFi: Find Your Edge


Home Menu

 





Indicator performance bottleneck


Discussion in NinjaTrader

Updated
      Top Posters
    1. looks_one Adamus with 8 posts (1 thanks)
    2. looks_two ratfink with 6 posts (3 thanks)
    3. looks_3 cory with 5 posts (3 thanks)
    4. looks_4 Koepisch with 2 posts (1 thanks)
      Best Posters
    1. looks_one Zondor with 1 thanks per post
    2. looks_two cory with 0.6 thanks per post
    3. looks_3 ratfink with 0.5 thanks per post
    4. looks_4 Adamus with 0.1 thanks per post
    1. trending_up 6,885 views
    2. thumb_up 9 thanks given
    3. group 4 followers
    1. forum 24 posts
    2. attach_file 1 attachments




 
Search this Thread

Indicator performance bottleneck

  #11 (permalink)
 
Adamus's Avatar
 Adamus 
London, UK
 
Experience: Beginner
Platform: NinjaTrader, home-grown Java
Broker: IB/IQFeed
Trading: EUR/USD
Posts: 1,085 since Dec 2010
Thanks Given: 471
Thanks Received: 789


ratfink View Post
Just another quick point, getting things up into the milli-second rather than micro-second levels usually takes memory or even hard page faults to become an issue, have you eliminated that side of things? (i.e. the TM is showing (100/number-of-cores)% flat-out for Ninja and no hard faults so it is all cpu). Would be unusual but not unknown, just depends what you are doing.

I had to look up what hard faults are and then I discovered that my resource monitor doesn't display properly, according to Microsoft the work-around for an incompatibility with IE10 is that I reduce my display font size to 100%, but Windows now wants me to log out and log back in so this will have to wait.

I see a 25% CPU utilisation which is 100% on one core when loading the indi. As I said can't tell yet about hard faults (what should I see?)

You can discover what your enemy fears most by observing the means he uses to frighten you.
Follow me on Twitter Visit my NexusFi Trade Journal Started this thread Reply With Quote

Can you help answer these questions
from other members on NexusFi?
REcommedations for programming help
Sierra Chart
NT7 Indicator Script Troubleshooting - Camarilla Pivots
NinjaTrader
Pivot Indicator like the old SwingTemp by Big Mike
NinjaTrader
Increase in trading performance by 75%
The Elite Circle
Better Renko Gaps
The Elite Circle
 
Best Threads (Most Thanked)
in the last 7 days on NexusFi
Just another trading journal: PA, Wyckoff & Trends
34 thanks
Tao te Trade: way of the WLD
24 thanks
GFIs1 1 DAX trade per day journal
17 thanks
Vinny E-Mini & Algobox Review TRADE ROOM
13 thanks
My NQ Trading Journal
12 thanks
  #12 (permalink)
 
ratfink's Avatar
 ratfink 
Birmingham UK
Market Wizard
 
Experience: Intermediate
Platform: NinjaTrader
Broker: TST/Rithmic
Trading: YM/Gold
Posts: 3,633 since Dec 2012
Thanks Given: 17,423
Thanks Received: 8,425


Adamus View Post
I see a 25% CPU utilisation which is 100% on one core when loading the indi. As I said can't tell yet about hard faults (what should I see?)

Then it is just a total cpu hog so the hard faults will likely be showing zero anyway and can be ignored. Definitely check for redundant drawing, calculation and object allocation operations, poor data fetch/create methods, excessive routine calling, unexpected looping, etcetera. Tests including dumb prints on small sets, eliminations and and binary chop style commenting out, your mission, should you choose to accept it, starts now.

Travel Well
Visit my NexusFi Trade Journal Reply With Quote
Thanked by:
  #13 (permalink)
 
Adamus's Avatar
 Adamus 
London, UK
 
Experience: Beginner
Platform: NinjaTrader, home-grown Java
Broker: IB/IQFeed
Trading: EUR/USD
Posts: 1,085 since Dec 2010
Thanks Given: 471
Thanks Received: 789



cory View Post
set a calculation kill switch on after calculation on history data is done.

hi cory, at first I didn't understand and just thought 'oh well' but then I saw you have an awesome 3,777 thank-yous and a higher thank-you to post ratio so I figure what you said is probably well worth heeding and I better find out what you mean. What confuses me is that all the calculations I do on history data need to be on every live bar as well, and in fact I don't think I've ever written anything for Ninja where that wasn't so. I do occasionally use the 'Historical' flag to switch when there is something hacky going on with historical vs live data or processing, but usually not. Could you expand a little on what you meant? Thanks.

You can discover what your enemy fears most by observing the means he uses to frighten you.
Follow me on Twitter Visit my NexusFi Trade Journal Started this thread Reply With Quote
  #14 (permalink)
 
cory's Avatar
 cory 
virginia
 
Experience: Intermediate
Platform: ninja
Trading: NQ
Posts: 6,098 since Jun 2009
Thanks Given: 877
Thanks Received: 8,090


Adamus View Post
hi cory, at first I didn't understand and just thought 'oh well' but then I saw you have an awesome 3,777 thank-yous and a higher thank-you to post ratio so I figure what you said is probably well worth heeding and I better find out what you mean. What confuses me is that all the calculations I do on history data need to be on every live bar as well, and in fact I don't think I've ever written anything for Ninja where that wasn't so. I do occasionally use the 'Historical' flag to switch when there is something hacky going on with historical vs live data or processing, but usually not. Could you expand a little on what you meant? Thanks.

see if this help

Quoting 
.....

public class NoGapBarbyBar : Indicator
{
#region Variables
// Wizard generated variables
// User defined variables (add any user defined variables below)
private DateTime currentDate = Cbi.Globals.MinDate;
private DateTime now;
private DateTime prevDay;
private DateTime prev2Day;
private DateTime prev3Day;


.....
#endregion

/// <summary>
/// This method is used to configure the indicator and is called once before any bar data is loaded.
/// </summary>
protected override void Initialize()
{
CalculateOnBarClose = true;
Overlay = true;


now = DateTime.Today; // today date
prevDay = now.AddDays(-1); // yesterday date
prev2Day = now.AddDays(-2);
prev3Day = now.AddDays(-3);
....


}

/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate()
{

// do one (firsttickofbar) for each live bar (bar date = today date) only
//
if (FirstTickOfBar && Time[0].Date == now)
{

// Print("open 0 "+Open[0]+ " close 1 " +Close[1] + " open 1 "+Open[1] + "Close 2 "+Close[2] + " open 2 "+Open[2]);
// do calculation
.....

} // end first tick



} // end on bar update

...


Reply With Quote
Thanked by:
  #15 (permalink)
 
Adamus's Avatar
 Adamus 
London, UK
 
Experience: Beginner
Platform: NinjaTrader, home-grown Java
Broker: IB/IQFeed
Trading: EUR/USD
Posts: 1,085 since Dec 2010
Thanks Given: 471
Thanks Received: 789

Thanks Cory for that. I see what you mean but I am doing it the way it is for the very reason that I can do that. I need to seriously think about whether I want to carry on that way. I also found the main culprit so if I can't fix it, I'll be into major re-design territory.

Now got a smaller screen resolution to make the resource manager work and no page faults. I might have to get more powerful reading glasses though.


ratfink View Post
Tests including dumb prints on small sets, eliminations and and binary chop style commenting out, your mission, should you choose to accept it, starts now.

I should employ Dilbert Jayavarman via freelancer.com to help.

Dumb prints are my forte - no worries there - although I suspect the eliminations I've managed so far owe more to the curry I had last night

Binary chop style commenting out sounds like an art form.

My experiments so far revealed some fairly embarrassing dog food but nothing that would go further than a peer code review if I was gainfully employed plus I've learnt too much about C#

It seems that .NET linq allows you to do all sorts of cool stuff but it runs like a snail. In all my C# Ninjascripting naivety I just wanted to find out if 2 lists of objects are the same, so I did this:

 
Code
IEnumerable<SRLevel> firstNotSecond = mergedLevelsList.Except(
	otherMergedLevels);
IEnumerable<SRLevel> secondNotFirst = 
	otherMergedLevels.Except(mergedLevelsList);
if (firstNotSecond.Count() > 0) return false;
if (secondNotFirst.Count() > 0) return false;
return true;
That alone would have been alright but every now and again the routine needs to go over info from all the bars - which is exactly what everyone here was warning about.


I might be able to send back my laptop cooler when this is sorted.

You can discover what your enemy fears most by observing the means he uses to frighten you.
Follow me on Twitter Visit my NexusFi Trade Journal Started this thread Reply With Quote
Thanked by:
  #16 (permalink)
 
Adamus's Avatar
 Adamus 
London, UK
 
Experience: Beginner
Platform: NinjaTrader, home-grown Java
Broker: IB/IQFeed
Trading: EUR/USD
Posts: 1,085 since Dec 2010
Thanks Given: 471
Thanks Received: 789

I have achieved great performance with the OnBarUpdate after re-coding some of the loops I was doing, but I am still not satisfied with the performance of the Plot()

Can anybody who's been there give me a faster way of doing this:

'level' is my simple data class containing the prices to draw at and the bars to display on. I keep them in a list for each bar in a dictionary indexed by bar.

 
Code
for (int i = 0; i < BarsArray[0].Count; i++) //loop over all bars
{
    if (i < ChartControl.FirstBarPainted) continue;
    if (i > this.LastBarIndexPainted) continue;
    List<SRLevel> levels = srLevels[i];
    for (int x = 0; x < levels.Count; x++)
    {
        SRLevel level = levels[x];
        int leftX = ChartControl.GetXByBarIdx(BarsArray[0], i);
        int rightX = ChartControl.GetXByBarIdx(BarsArray[0], i + 1);
        int width = rightX - leftX; 
        // higher price is lower Y - Y origin is top
        int startY = ChartControl.GetYByValue(this, level.topY) - displayMargin; 
        int stopY;
        if (level.topY.Compare(level.bottomY, PRECISION) == 0)
            stopY = startY + displayMargin;
        else
            stopY = ChartControl.GetYByValue(this, level.bottomY) + displayMargin; 
        int height = stopY - startY;
        if (height < 1) height = 1;
        int labelY = 0; 
        //LastBarPainted only references primary dataseries
        if (level.behaviour == SRLevelBehaviour.SUPPORT)
        {
            brush.Color = supportColor;
            labelY = stopY + textFont.Height / 2; // labelY is for text
        }
        else if (level.behaviour == SRLevelBehaviour.RESISTANCE)
        {
            brush.Color = resistanceColor;
            labelY = startY - textFont.Height;
        }  
        graphics.FillRectangle(brush, leftX, startY, width, height);
    }
}
It seems ChartControl.GetXByBarIdx() and GetYByValue() are costly operations. Is there any other way of doing this?

You can discover what your enemy fears most by observing the means he uses to frighten you.
Follow me on Twitter Visit my NexusFi Trade Journal Started this thread Reply With Quote
  #17 (permalink)
 
cory's Avatar
 cory 
virginia
 
Experience: Intermediate
Platform: ninja
Trading: NQ
Posts: 6,098 since Jun 2009
Thanks Given: 877
Thanks Received: 8,090

ninja performance tip
Last Historical Bar? - [AUTOLINK]NinjaTrader[/AUTOLINK] Support Forum

Reply With Quote
Thanked by:
  #18 (permalink)
 Koepisch 
@ Germany
 
Experience: Beginner
Platform: NinjaTrader
Broker: Mirus Futures/Zen-Fire
Trading: FDAX
Posts: 569 since Nov 2011
Thanks Given: 440
Thanks Received: 518


Adamus View Post
...
It seems ChartControl.GetXByBarIdx() and GetYByValue() are costly operations. Is there any other way of doing this?

@Adamus: Nice coding so far. You can test that you don't call the Get.. functions every time. If you call it 2 times for 2 consecutive IDXs then you can interpolate the other values. You can also check if "List<SRLevel> levels = srLevels[i];" is copying your list (worse) - there is no need for this, work with srlevels[i] directly.

Reply With Quote
  #19 (permalink)
 
Tasker_182's Avatar
 Tasker_182 
Cedar Rapids, iowa
Legendary Market Wizard
 
Experience: Intermediate
Platform: Ninjatrader
Broker: Ninjatrader - Continuum
Posts: 716 since Aug 2009
Thanks Given: 476
Thanks Received: 1,401


cory View Post
see if this help

Hey Cory,

Your example references FirstTickOfBar and appears to be CalcOnbarclose=true. According to the ninja reference this would not work.

"10.4.3.26 FirstTickOfBar
Definition
Indicates if the incoming tick is the first tick of a new bar. This property is only of value in
scripts that run tick by tick which is when the CalculateOnBarClose property is set to false."

Did I miss something?

Regards,

Be yourself; everyone else is already taken. Oscar Wilde
Reply With Quote
  #20 (permalink)
 
cory's Avatar
 cory 
virginia
 
Experience: Intermediate
Platform: ninja
Trading: NQ
Posts: 6,098 since Jun 2009
Thanks Given: 877
Thanks Received: 8,090



Tasker_182 View Post
Hey Cory,

Your example references FirstTickOfBar and appears to be CalcOnbarclose=true. According to the ninja reference this would not work.

"10.4.3.26 FirstTickOfBar
Definition
Indicates if the incoming tick is the first tick of a new bar. This property is only of value in
scripts that run tick by tick which is when the CalculateOnBarClose property is set to false."

Did I miss something?

Regards,

use FirstTickOfBar so you don't have to set CalcOnbarclose=true.

Reply With Quote




Last Updated on December 9, 2013


© 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