Welcome to NexusFi: the best trading community on the planet, with over 200,000 members Sign Up Now for Free
Genuine reviews from real traders, not fake reviews from stealth vendors
Quality education from leading professional traders
We are a friendly, helpful, and positive community
We do not tolerate rude behavior, trolling, or vendors advertising in posts
We are here to help, just let us know what you need
You'll need to register in order to view the content of the threads and start contributing to our community. It's free for basic access, or support us by becoming an Elite Member -- discounts are available after registering.
-- Big Mike, Site Administrator
(If you already have an account, login at the top of the page)
I've been trying hard with chat gpt and my own modest dev skills to code a CAGR custom performance metric for NT8, but I'm stuck : I keep getting a NaN value. If anybody could look at the code and give an advice that would be amazing (i'm sure a lot of people here using ninja could use a CAGR...).
Code :
//
// Copyright (C) 2024, NinjaTrader LLC <www.ninjatrader.com>.
// NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
//
#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.ComponentModel.DataAnnotations; // Added for DisplayAttribute
using NinjaTrader.Cbi; // For Account, Currency, AccountItem references
#endregion
namespace NinjaTrader.NinjaScript.PerformanceMetrics
{
public class CAGRPerformanceMetric : PerformanceMetric
{
private double startValue; // Start value of the portfolio
private double endValue; // End value of the portfolio
private double totalDurationYears; // Duration of the performance in years
private DateTime startTime; // Start time of the first trade
private DateTime endTime; // End time of the last trade
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "CAGRPerformanceMetric"; // Name shown in UI
startValue = 0.0;
endValue = 0.0;
totalDurationYears = 0.0;
}
else if (State == State.Configure)
{
Values = new double[1]; // Only one value: CAGR
}
else if (State == State.Active)
{
// Reset all values at the start of a new backtest run
startValue = 0.0;
endValue = 0.0;
totalDurationYears = 0.0;
startTime = DateTime.MinValue;
endTime = DateTime.MinValue;
Array.Clear(Values, 0, Values.Length);
}
}
// This is called as each trade is added
protected override void OnAddTrade(Cbi.Trade trade)
{
// Initialize startValue and startTime at the first trade
if (startValue == 0.0 && trade.Entry != null)
{
startValue = trade.Entry.Account.Get(Cbi.AccountItem.RealizedProfitLoss, Cbi.Currency.UsDollar);
startTime = trade.Entry.Time;
}
// Update the endValue and endTime at each trade exit
if (trade.Exit != null)
{
endValue = trade.Exit.Account.Get(Cbi.AccountItem.RealizedProfitLoss, Cbi.Currency.UsDollar);
endTime = trade.Exit.Time;
}
// If we have both a start and end time, calculate the duration
if (startTime != DateTime.MinValue && endTime != DateTime.MinValue)
{
totalDurationYears = (endTime - startTime).TotalDays / 252; // Approximate years calculation
}
// Calculate CAGR if duration is valid
if (startValue > 0 && endValue > 0 && totalDurationYears > 0)
{
Values[0] = CalculateCAGR(startValue, endValue, totalDurationYears);
}
else
{
Values[0] = 0; // Handle cases where values are not yet valid
}
}
// 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 == 1 && unit == Cbi.PerformanceUnit.Percent)
{
if (tmp[0] != 0)
return tmp[0].ToString("P"); // Format as a percentage
else
return "0%"; // Handle zero values gracefully
}
return "N/A"; // Handle null or unexpected formats
}
[Display(ResourceType = typeof(Custom.Resource), Description = "", Name = "CAGR", Order = 0)]
public double[] Values { get; private set; }
}
}
Can you help answer these questions from other members on NexusFi?