A confusing feature of MultiCharts .NET is that drawings made while the bar hasn’t closed are removed on the next script calculation. And so arrows, trend lines, or text boxes are visible for a second or so before disappearing. How can that behaviour be changed?

The RecoverDrawings attribute: removing intra-bar generated drawings (or not)

A C# attribute is a class that adds metadata to a code element (Dorman, 2010), and can act as a modifier by doing so (Liberty & MacDonald, 2009). In MultiCharts .NET attributes are used to set certain script options.

One of those attributes is RecoverDrawings, which can remove or keep intra-bar generated drawings after the next script calculation (MultiCharts, 2014; MultiCharts Wiki, 2014). A drawing is a text box, trend line, or arrow (see MultiCharts, 2014).

Like MouseEvents, RecoverDrawings cannot be set manually but only by adding the attribute to your code.

Setting the RecoverDrawings attribute in MultiCharts .NET

Set RecoverDrawings to false to preserve all programmatically created drawings on the chart (MultiCharts, 2014; MultiCharts Wiki, 2014), like so:

[RecoverDrawings(false)]
public class Example_RecoverDrawings : IndicatorObject
{
    // Script code
}

To only keep drawings that were made on bar close, set the attribute to true (MultiCharts Wiki, 2014), like this:

[RecoverDrawings(true)]
public class Example_RecoverDrawings : IndicatorObject
{
    // Script code
}

When the attribute isn’t added to the code, it defaults to true (MultiCharts Wiki, 2014), and so intra-bar generated drawings are removed by default.

Example: RecoverDrawings and plotting arrows in MultiCharts .NET

Let’s create a few arrows to see the effect of this attribute:

[RecoverDrawings(true), SameAsSymbol(true)]
public class Example_RecoverDrawings : IndicatorObject
{
    public Example_RecoverDrawings(object _ctx) : base(_ctx) { }

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

    bool alreadyPlotted = false;

    protected override void CalcBar()
    {
        if (Bars.LastBarOnChart && alreadyPlotted == false && 
            Bars.Status == EBarState.Inside)
        {
            for (int i = 0; i < 10; i++)
            {
                ChartPoint chartLocation = new ChartPoint(
                    Bars.Time[i], Bars.High[i] + Bars.Range(i));

                Output.WriteLine("Plotting arrow at {0} on {1}",
                    Bars.High[i] + Bars.Range(i), 
                    Bars.Time[i].ToShortTimeString());

                DrwArrow.Create(chartLocation, true);
            }

            alreadyPlotted = true;
        }
    }

    //> Plotting arrow at 1,02531 on 19:35
    //> Plotting arrow at 1,02661 on 19:25
    //> Plotting arrow at 1,02866 on 19:15
    //> Plotting arrow at 1,02854 on 19:05
    //> Plotting arrow at 1,02591 on 18:55
    //> Plotting arrow at 1,02653 on 18:45
    //> Plotting arrow at 1,02783 on 18:35
    //> Plotting arrow at 1,02728 on 18:25
    //> Plotting arrow at 1,0291 on 18:15
    //> Plotting arrow at 1,02929 on 18:05
}

Besides RecoverDrawings, the SameAsSymbol attribute is set to true so that the indicator is plotted on the data series (and not its own subchart).

In the StartCalc() method we set the indicator’s MaxBarsBack value to 20 with the ExecInfo.MaxBarsBack property (see PowerLanguage .NET Help, n.d.). By explicitly setting the number of bars that the indicator uses for its calculations, we prevent that the script guesses this value (which causes a script recalculation and messes with our drawings).

Then a Boolean variable (alreadyPlotted) is declared and assigned its initial value of false. This variable is used later on to prevent arrows from being created repeatedly.

Drawings arrows on the MultiCharts .NET price chart

The CalcBar() method starts with an if statement that require three things to evaluate to true. First, the current bar needs to be the last, in which case Bars.LastBarOnChart returns true (see PowerLanguage .NET Help, n.d.). Second, the alreadyPlotted variable needs to be false. And third, the current price needs to be inside the bar so that the bar hasn’t closed yet (EBarState.Inside). This latter ensures we create intra-bar drawings.

When all three conditions evaluate to true, a for loop begins that loops 10 times. With each cycle, a ChartPoint variable named chartLocation is created that consists out of the bar’s time (Bars.Time[i]) and the bar’s high plus the range (Bars.High[i] + Bars.Range(i)). By adding the range we plot arrows a little bit away from the bar, and with the i variable data is retrieved for the previous bars.

Output.WriteLine() then prints information about the arrow’s location to the PowerLanguage .NET Editor. This way we can verify that the code executed, even when the arrows are removed by RecoverDrawings.

Then an arrow is created with the DrwArrow.Create() method (see MultiCharts, 2014). This method uses two arguments here: the ChartPoint location where the arrow needs to be placed (which we just stored in the chartLocation variable) and whether the arrow should point up (false) or down (true).

The last statement sets the alreadyPlotted variable to true. This causes the if statement (which required that this variable was false) to be only executed once. And so we don’t end up with a bunch of arrows on the chart.

The effect of RecoverDrawings enabled or disabled

When the above indicator has the RecoverDrawings attribute set to true, it’s drawings aren’t persistent:

MultiCharts .NET RecoverDrawings - set to true

But when the attribute is set to false, our arrows created intra-bar are retained:

MultiCharts .NET RecoverDrawings - set to false

By the way, should you change something like an attribute while the indicator is already added to the chart, the script needs to be removed and re-added in order to see the effect of the modified code (see Henry MultiCharts, 2014).

Summary

The RecoverDrawings attribute specifies whether intra-bar generated drawings (text boxes, trend lines, and arrows) should be removed with the next script calculation (when set to true) or kept on the chart (when false). The default behaviour is to remove these intra-bar drawings.


References

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

Henry MultiCharts (2014, December 11). MultiCharts .NET FAQ – forum discussion. Retrieved on January 25, 2015, from http://www.multicharts.com/discussion/viewtopic.php?f=19&t=45848#p111375

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

MultiCharts (2014). MultiCharts .NET Programming Guide (version 1.1). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.1.pdf

MultiCharts Wiki (2014, January 23). RecoverDrawings. Retrieved on January 27, 2015, from http://www.multicharts.com/trading-software/index.php/RecoverDrawings

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