Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Custom Performance Metric

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • NinjaTrader_ChelseaB
    replied
    Hello TAJTrades,

    The SampleCumProfit included with NinjaTrader provides sample code.

    On lines 38 through 42 of the sample, the metric value is assigned in OnAddTrade().
    For Currency, the sample code is assigning the trade.ProfitCurrency on line 38. This is the value showing in the summary results.

    In your code you posted in post #1, you have:
    Values[(int)Cbi.PerformanceUnit.Currency] += trade.ProfitCurrency;

    This is where you are setting the performance value to the net profit and it's in OnAddTrade(). Set this to 5 if you want it to have a value of 5. (Use '=' instead of '+=' to make the value 5 exactly and not accumulate 5 for each trade.


    Your initial inquiry appeared to be asking about the merged results from total row and not the metric value for individual iterations. This is what would be calculated in OnMergePerformanceMetric().



    Below is a link to an additional example custom metric script and performance metric script.

    Leave a comment:


  • TAJTrades
    replied
    Not finding any joy here. Did a search on "onAddTrade" and did not find any working examples. Also tried adding in some code in "OnAddTrade" and nothing.

    Maybe I am not making myself clear. All I am trying to do is create a Custom PerformanceMetric that acts just like the PerformanceMetric "R squared / Ulcer Index / Sortino ratio / Sharp ratio" above it when Backtesting, Optimizing or in Trade Performance.

    The Metric I want to create is RoMaD (Return over Maximum Drawdown). The math is simply:

    TradesPerformance.NetProfit / TradesPerformance.Currency.Drawdown.


    Everything I have tried somehow defaults back to displaying Total net profit.

    This image is for BackTest.
    Click image for larger version

Name:	NT Support Backtest.png
Views:	81
Size:	74.9 KB
ID:	1333927


    This is for Optimization on a single Instrument

    Click image for larger version

Name:	NT Support Optimized.png
Views:	57
Size:	83.4 KB
ID:	1333928

    Do you know of any sample code that will do this? Can we work together to create some Sample Code for other users?

    Thanks

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello TAJTrades,

    So instead of the merge results, you want to change the value in individual backtest results, correct?

    Set the Values[] collection to 5 in OnAddTrade().

    Leave a comment:


  • TAJTrades
    replied
    I can duplicate what you have shown in the image. The issue with OnMergePerformanceMetric makes sense.

    However, I am trying to get the $5.00 to calculate for each instrument in your example. When I do a Backtest on 1 Instrument the value shown is the same Total Net Profit.

    Can this be done?

    Is there something like this that does not require the "Merge" part: protected override void OnPerformanceMetric(PerformanceMetricBase target)



    I have searched high and low for some sample code and have come up empty.

    Thanks.



    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello TAJTrades,

    I'm finding the OnMergePerformanceMetric is only for merged results.

    As an example if you backtest over an instrument list (called a basket test) there will be a Combined results row. When selecting this row, the summary will show the 5 value you have hard coded.

    Click image for larger version  Name:	2025-02-05_07-27-49.png Views:	0 Size:	81.4 KB ID:	1333664

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello TAJTrades,

    Thank you for your patience. I am looking into this on my end.

    Leave a comment:


  • TAJTrades
    replied
    Chelsea,

    I rebooted the computer and restarted NT8 8.1.4.1 (latest download)

    MyCustomPerformanceMetric is showing the same value as SampleCumProfit and top line Total net profit.

    I tried with Backtest and Optimization. Same results.



    Click image for larger version

Name:	Nt Support 2.png
Views:	88
Size:	41.2 KB
ID:	1333178

    Any other suggestions?

    Thanks for your help.

    Leave a comment:


  • TAJTrades
    replied
    After making the assignment may I confirm you have compiled the script without errors? Compiles. No Errors

    If you restart NinjaTrader and run a new backtest, does the merged values show 5? Will reboot computer and try.

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello TAJTrades,

    After making the assignment may I confirm you have compiled the script without errors?

    If you restart NinjaTrader and run a new backtest, does the merged values show 5?

    Leave a comment:


  • TAJTrades
    started a topic Custom Performance Metric

    Custom Performance Metric

    This Performance Metric is almost identical the "SampleCumProfit".

    Would you please educate me on why this Performance Metric is displaying the Total Net Profit value and not 5.00 that is hard coded in protected override void OnMergePerformanceMetric.



    PHP Code:
    //This namespace holds Performance metrics in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.PerformanceMetrics
    {
        public class MyCustomPerformanceMetric : PerformanceMetric
        {
            private Cbi.Currency denomination = (Cbi.Currency) (-1);
            
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"Enter the description for your new custom Performance Metric here.";
                    Name                                        = "MyCustomPerformanceMetric";
                }
                else if (State == State.Configure)
                {
                    Values    = new double[5];                    // There needed to be one value per Cbi.PerformanceUnit, which is why the values are managed in an array of length "ValueArrayLength"
                }
                else if (State == State.Active)    
                {
                    Array.Clear(Values, 0, Values.Length);        // Needed to be reset before every backtest iteration.
                }
            }
    
            protected override void OnAddTrade(Trade trade)
            {
                if (denomination == (Cbi.Currency) (-1))
                    denomination = trade.Exit.Account.Denomination;
    
                Values[(int)Cbi.PerformanceUnit.Currency]    += trade.ProfitCurrency;
                Values[(int)Cbi.PerformanceUnit.Percent]    = (1.0 + Values[(int)Cbi.PerformanceUnit.Percent]) * (1.0 + trade.ProfitPercent) - 1;
                Values[(int)Cbi.PerformanceUnit.Pips]        += trade.ProfitPips;
                Values[(int)Cbi.PerformanceUnit.Points]        += trade.ProfitPoints;
                Values[(int)Cbi.PerformanceUnit.Ticks]        += trade.ProfitTicks;
            }
    
            // This is called as the values of a trade metric are saved, which occurs e.g. in the strategy analyzer on optimizer runs
            protected override void OnCopyTo(PerformanceMetricBase target)
            {
                // You need to cast, in order to access the right type
                MyCustomPerformanceMetric targetMetrics = (target as MyCustomPerformanceMetric);
    
                if (targetMetrics != null)
                    Array.Copy(Values, targetMetrics.Values, Values.Length);
            }
    
            protected override void OnMergePerformanceMetric(PerformanceMetricBase target)
            {
                // You need to cast, in order to access the right type
                MyCustomPerformanceMetric targetMetrics = (target as MyCustomPerformanceMetric);
    
                // This is just a simple weighted average sample
                if (targetMetrics != null && TradesPerformance.TradesCount + targetMetrics.TradesPerformance.TradesCount > 0)
                    for (int i = 0; i < Values.Length; i++)
                    {
                        targetMetrics.Values[i] = 5.00;
                        //    Will eventually  be:
                        //    TradesPerformance.NetProfit / TradesPerformance.Currency.Drawdown
                    }
            }
    
            // The display attribute determines the name of the performance value on the grid (the actual property name below is irrelevant for that matter)
            [Display(Name = "MyCustomPerformanceMetric", Description = "Enter the description for your new custom Performance Metric here.", Order = 0)]
            public double[] Values
            { get; private set; }
    
            #region Miscellaneous
            // The format method allows you to customize the rendering of the performance value on the summary grid.
            public override string Format(object value, Cbi.PerformanceUnit unit, string propertyName)
            {
                double[] tmp = value as double[];
                if (tmp != null && tmp.Length == 5)
                    switch (unit)
                    {
                        case Cbi.PerformanceUnit.Currency    : return Core.Globals.FormatCurrency(tmp[0], denomination);
                        case Cbi.PerformanceUnit.Percent    : return tmp[1].ToString("P");
                        case Cbi.PerformanceUnit.Pips        : return Math.Round(tmp[2]).ToString(Core.Globals.GeneralOptions.CurrentCulture);
                        case Cbi.PerformanceUnit.Points        : return Math.Round(tmp[3]).ToString(Core.Globals.GeneralOptions.CurrentCulture);
                        case Cbi.PerformanceUnit.Ticks        : return Math.Round(tmp[4]).ToString(Core.Globals.GeneralOptions.CurrentCulture);
                    }
                return value.ToString();            // should not happen
            }
            #endregion        
    
        }
    }&#8203; 
    
    This is the image of the Analyzer:
    Click image for larger version

Name:	Nt Support 1.png
Views:	136
Size:	30.6 KB
ID:	1333149


    ​Thanks.

Latest Posts

Collapse

Topics Statistics Last Post
Started by CaptainJack, 04-24-2026, 11:07 PM
0 responses
52 views
0 likes
Last Post CaptainJack  
Started by Mindset, 04-21-2026, 06:46 AM
0 responses
137 views
0 likes
Last Post Mindset
by Mindset
 
Started by M4ndoo, 04-20-2026, 05:21 PM
0 responses
195 views
0 likes
Last Post M4ndoo
by M4ndoo
 
Started by M4ndoo, 04-19-2026, 05:54 PM
0 responses
105 views
0 likes
Last Post M4ndoo
by M4ndoo
 
Started by cmoran13, 04-16-2026, 01:02 PM
0 responses
143 views
0 likes
Last Post cmoran13  
Working...
X