Situation
You want to know how to output numeric values to the Output Window with custom formatting, such as currency symbols or specifying the number of decimals.

Programming example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true), UpdateOnEveryTick(false)]
    public class Example_NumericStandardFormatStrings : IndicatorObject
    {
        public Example_NumericStandardFormatStrings(object _ctx) : base(_ctx) { }

        private bool printOnce;

        protected override void StartCalc()
        {
            ExecInfo.MaxBarsBack = 10;

            printOnce = false;

            Output.Clear();
        }
        
        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart && !printOnce)
            {
                Output.Write("Previous close ({0}): {0:F2}\t", Bars.Close[1]);
                Output.WriteLine(Bars.Close[1].ToString("F2"));

                Output.WriteLine("Currency closing price: {0:C5}", Bars.Close[0]);

                double value = 15875.59;
                Output.WriteLine("\r\n{0} with a group separator: {0:N2}", value);
                Output.WriteLine("Or in scientific notation: {0:E2}", value);

                double priceGain = (Bars.Close[0] - Bars.Close[10]) / Bars.Close[10];
                Output.WriteLine("\r\nPrice gain ({0}) in percent: {0:P2}", priceGain);

                printOnce = true;
            }
        }
    }
}

Output of the programming example

The example indicator generates the following text to the Output Window:

Previous close (0,79501): 0,80  0,80
Currency closing price: € 0,79519

15875,59 with a group separator: 15.875,59
Or in scientific notation: 1,59E+004

Price gain (-0,00113052544310318) in percent: -0,11 %

The PowerLanguage .NET Editor Output Window

The PowerLanguage .NET Editor has an Output Window for easily printing information from a trading strategy or indicator. It can be used in any of the override methods (MultiCharts, 2013) with three methods (PowerLanguage .NET Help, n.d.):

  • Output.WriteLine() and Output.Write() both write text to the Output Window, but the first also adds a line break;
  • The Output.Clear() method removes all text in the Output Window.

To determine how values are displayed in the Output Window, C#’s format specifiers can be used.

Example of the output window in MultiCharts .NET

To enable the Output Window, go to ‘View’ in the menu bar.

See Outputting data to the Output Window, ‘debugging’ with the Output Window, escape characters in the Output Window and the Output Window and substitution parameters to learn even more about hte Output Window.

Formatting numeric values with format specifiers in C#

Controlling how a value (such as a numeric variable) is converted to a string can be done with a format string, of which there are two kinds (Albahari & Albahari, 2012; Dorman, 2010):

  • Standard format strings have a single letter (called the format specifier) and an optional digit (the precision specifier);
  • Custom format strings allow for micromanaging every character in the output with a template (custom format strings are outside the scope of this article).

These format strings can be used in two ways (Dorman, 2010; Microsoft Developer Network [MSDN], n.d. a): by calling the object’s overloaded ToString() method and passing in the specifier as an argument. Or with a substitution parameter that includes a semicolon and the specifier. Both approaches are used in the example.

The standard numeric format specifiers in C#

The available standard format specifiers for numeric values in C# are the following (Albahari & Albahari, 2012; Dorman, 2010; MSDN, n.d. a):

Format specifier Meaning Meaning of the optional precision specifier Notes
"G" or "g" General, "default" string. Limits the precision to the number of significant digits in total.

"G3" displays 12345 as 1.23E04.
Scientific notation is used for small or large numbers.

Defaults to two decimal places.
"F" or "f" Fixed point. The number of decimals to round to.

"F2" displays 123.456 as 123.46.
Zeros are added to the end of the string to achieve the specified number of decimals.
"N" or "n" Fixed point with group separator. The number of decimals to round to.

"N2" displays 1975.2 as 1,975.20.
Includes both a group separator (1000s) and decimals.
"D" or "d" Pad left with leading zeros. Minimum number of numbers to display.

"D4" displays 12 as 0012.
Integral types only.

Results in integer digits.

Leading zeros are added when the precision specifier is larger than the value.
"E" or "e" Exponential (scientific) notation. The number of decimals to display.

"E2" displays 56789 as 5.68E+004.
With no precision specifier, six-digit precision is used.

The exponent always has a plus or minus sign and a minimum of three digits (zeros are added to meet this minimum, when needed).
"C" Currency. The number of decimal digits to display.

"C4" displays 1.50 as €1.5000.
A fractional value is rounded when it has more decimals than the precision specifier.

The returned currency sign depends on the culture settings of the operating system.
"P" or "p" Percent. The number of decimal digits to display.

"P1" displays -0.39142 as -39,1%.
Multiplies the number by 100 and converts it to a string that represents a percentage.
"X" or "x" Hexadecimal. The minimum number of digits in the result string.

"X4" returns 47 as 002F.
Integrals only.

Use X for uppercase hex digits and x for lowercase hex digits.

When required, the number is padded with zeros to the left to produce the number of digits given by the precision specifier.
"R" or "r" Round-trip. Ignored.

1f / 3f with "R" returns in 0.333333343.
Supported by Single, Double, and BigInteger.

Results in a string that can round-trip to an identical number. This means that a number converted to a string with `”R”` can be converted back to a number without a loss of significant digits.

Table note: The integral types, referred to in the table, are sbyte, byte, short, ushort, int, uint, long, and ulong (MSDN, n.d. b).

MultiCharts .NET programming example

The example begins with setting MultiCharts .NET attributes:

[SameAsSymbol(true), UpdateOnEveryTick(false)]

With setting SameAsSymbol to true the indicator does not create a subchart, while UpdateOnEveryTick set to false ensures the indicator is calculated once per bar.

Setting the MaxBarsBack and clearing the Output Window

The second part of the example is the following:

private bool printOnce;

protected override void StartCalc()
{
    ExecInfo.MaxBarsBack = 10;

    printOnce = false;

    Output.Clear();
}

A Boolean variable (printOnce) is declared here and will be used later to determine if the output has been printed.

In the StartCalc() method, three things happen. First, the MaxBarsBack are set explicitly to 10. This prevents an automatic recalculation due to MaxBarsBack ‘auto-detect’. To learn more about MaxBarsBack, see what are ‘MaxBarsBack’ and how do they work?.

Second is the printOnce variable: since the StartCalc() method is executed at the beginning of every calculation cycle (MultiCharts, 2013), this variable is set back to false once per calculation. Third, the Output.Clear() method is called to tidy up the Output Window.

Formatting numeric values in the MultiCharts .NET Output Window

The CalcBar() override method is the last part of the example:

protected override void CalcBar()
{
    if (Bars.LastBarOnChart && !printOnce)
    {
        Output.Write("Previous close ({0}): {0:F2}\t", Bars.Close[1]);
        Output.WriteLine(Bars.Close[1].ToString("F2"));

        Output.WriteLine("Currency closing price: {0:C5}", Bars.Close[0]);

        double value = 15875.59;
        Output.WriteLine("\r\n{0} with a group separator: {0:N2}", value);
        Output.WriteLine("Or in scientific notation: {0:E2}", value);

        double priceGain = (Bars.Close[0] - Bars.Close[10]) / Bars.Close[10];
        Output.WriteLine("\r\nPrice gain ({0}) in percent: {0:P2}", priceGain);

        printOnce = true;
    }
}

The if statement evaluates two expressions: whether the current bar is the last bar on the chart (then Bars.LastBarOnChart returns true) and if the printOnce variable is false, which is tested with the logical not operator (!).

Printing numeric values with the fixed point format specifier

When both expressions evaluate to true, the body of the if statement is executed. It starts with outputting numeric values with a fixed point:

Output.Write("Previous close ({0}): {0:F2}\t", Bars.Close[1]);
Output.WriteLine(Bars.Close[1].ToString("F2"));

Here the close of the previous historical price bar (Bars.Close[1]) is printed to the Output Window in two ways:

The Output.Write() method has a string argument which includes the {0} substitution parameter. This placeholder occurs twice in the literal string: like usual ({0}) and with the fixed point format specifier with a precision specifier of 2 for two decimals ({0:F2}). For outlining, the tab escape character (\t) is added to the end of the string.

The Output.WriteLine() method (line 29) shows that format specifiers can also be used with the ToString() method: ToString("F2") converts the previous bar closing price to a string with 2 decimals.

These statements generate the following output:

Previous close (0,79501): 0,80  0,80

Converting a numeric value to a currency value

Next is creating a string with currency sign:

Output.WriteLine("Currency closing price: {0:C5}", Bars.Close[0]);

Here current bar price data is outputted with the currency format specifier and 5 decimals (C5). This generates the following output:

Currency closing price: € 0,79519

Fixed point and scientific notation in MultiCharts .NET

The next segment contains the following code:

double value = 15875.59;
Output.WriteLine("\r\n{0} with a group separator: {0:N2}", value);
Output.WriteLine("Or in scientific notation: {0:E2}", value);

The value double variable is used in two Output.WriteLine() method calls. First it is outputted with the fixed point (with thousands separator) format specifier and two decimals (N2). That output also contains the \r\n escape character which inserts a blank line to keep the line distinct from previous ones.

In the second statement the value variable is converted to a string with the "E" format specifier for scientific notation. Both lines (34 and 35) give the following output:

15875,59 with a group separator: 15.875,59
Or in scientific notation: 1,59E+004

Outputting numeric values as percentages in the PowerLanguage .NET Editor Output Window

The last part of the CalcBar() override method is the following:

double priceGain = (Bars.Close[0] - Bars.Close[10]) / Bars.Close[10];
Output.WriteLine("\r\nPrice gain ({0}) in percent: {0:P2}", priceGain);

printOnce = true;

The priceGain double variable calculates the single-period return between the current price bar (Bars.Close[0]) and a historical price bar (Bars.Close[10]). This variable is subsequently outputted with the percentage format specifier with 2 decimals (P2). This prints the following:

Price gain (-0,00113052544310318) in percent: -0,11 %

The last statement (line 40) sets the printOnce variable to false. By doing so, the body of the if statement is only executed once (see expression in line 26) per calculation cycle (see line 19 in the StartCalc() override method).

Key points

  • Outputting text to the PowerLanguage .NET Editor Output Window is done with the Output.Write() and Output.WriteLine() methods;
  • Standard format strings in C# allow for controlling how a numeric value is converted to a string;
  • These standard format strings consist out of a single letter (the format specifier) and an optional digit (the precision specifier);
  • Often used format specifiers are "F" (fixed point), "N" (fixed point with a thousands separator), "C" (currency), and "P" (percent).
References

Albahari, J. & Albahari, B. (2012). C# 5.0 in a Nutshell: The Definitive Reference (5th edition). Sebastopol, CA: O’Reilly Media.

Dorman, S. (2010). Sams Teach Yourself Visual C# 2010 in 24 Hours. Indianapolis, IN (USA): Sams/Pearson Education.

Microsoft Developer Network [MSDN] (n.d. a). Standard Numeric Format Strings. Retrieved on September 11, 2014, from http://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx

MSDN (n.d. b). Integral Types Table (C# Reference). Retrieved on September 10, 2014, from http://msdn.microsoft.com/en-us/library/exx3b86w.aspx

MultiCharts (2013). MultiCharts .NET Programming Guide (version 1.0). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.0.pdf

PowerLanguage .NET Help (n.d.). Retrieved on May 16, 2014, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm