Real usage of VariableObject

Questions about MultiCharts .NET and user contributed studies.
bobrovartiom
Posts: 8
Joined: 12 Mar 2016
Has thanked: 1 time

Real usage of VariableObject

Postby bobrovartiom » 13 Mar 2016

Hi all. It seems I am stuck with understanding what for VariableObject and VariableSeries are needed. I meet them in many examples, uderstand their functionality, but do not get why we can not use the simple int (or double, or short - does not matter) insted of them.
Here is the code of pre-build Signal MovAvg_Cross_LE
[+] code here

Code: Select all

using System;
using PowerLanguage.Function;
namespace PowerLanguage.Strategy
{
public class MovAvg_Cross_LE : SignalObject
{
private AverageFC m_AverageFC;

private VariableObject<Int32> m_Counter;

private IOrderMarket m_MACrossLE;

public MovAvg_Cross_LE(object ctx) :
base(ctx)
{
Length = 9;
ConfirmBars = 1;
}

private ISeries<double> Price { get; set; }

[Input]
public int Length { get; set; }

[Input]
public int ConfirmBars { get; set; }

protected override void Create(){
m_AverageFC = new AverageFC(this);
m_MACrossLE =
OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, "MACrossLE", EOrderAction.Buy));
m_Counter = new VariableObject<int>(this);
}

protected override void StartCalc(){
Price = Bars.Close;
m_AverageFC.price = Price;
m_AverageFC.length = Length;
}


protected override void CalcBar(){
double m_Avg = m_AverageFC[0];
if (PublicFunctions.DoubleGreater(Price[0], m_Avg)){
++m_Counter.Value;
}
else{
m_Counter.Value = 0;
}
if (PublicFunctions.DoubleGreater(Bars.CurrentBar, ConfirmBars)
&& m_Counter.Value == ConfirmBars)
{
m_MACrossLE.Send();
}
}
}
}
Can anyone explain why we create m_counter variable as private VariableObject, but not as simple int in this case? It would work the sme way, but why to use something that make code less readable? I am sure there is a reason here and think if I get it so I get the functionality of the VariableObject. Thanks.

User avatar
JoshM
Posts: 2195
Joined: 20 May 2011
Location: The Netherlands
Has thanked: 1544 times
Been thanked: 1565 times
Contact:

Re: Real usage of VariableObject

Postby JoshM » 14 Mar 2016

Can anyone explain why we create m_counter variable as private VariableObject, but not as simple int in this case? It would work the sme way, but why to use something that make code less readable? I am sure there is a reason here and think if I get it so I get the functionality of the VariableObject. Thanks.
I'm also curious to hear why `VariableObject<T>` is used here; I agree with you that it needlessly complicates things.

Actually, speaking of 'real usage' for `VariableObject<T>`: I cannot think of any. If I search all my script files in Visual Studio, then I've only used `VariableObject<T>` once, and that was to explore how it works..

I suppose that other people may use it much more often than I do, but for my purposes it's always more intuitive (for me) to use a regular collection or a simple counting variable.

This probably also just shows that there are more ways to approach something, and that it's also a matter of personal preference which approach to use.

bobrovartiom
Posts: 8
Joined: 12 Mar 2016
Has thanked: 1 time

Re: Real usage of VariableObject

Postby bobrovartiom » 14 Mar 2016

Can anyone explain why we create m_counter variable as private VariableObject, but not as simple int in this case? It would work the sme way, but why to use something that make code less readable? I am sure there is a reason here and think if I get it so I get the functionality of the VariableObject. Thanks.
I'm also curious to hear why `VariableObject<T>` is used here; I agree with you that it needlessly complicates things.

Actually, speaking of 'real usage' for `VariableObject<T>`: I cannot think of any. If I search all my script files in Visual Studio, then I've only used `VariableObject<T>` once, and that was to explore how it works..

I suppose that other people may use it much more often than I do, but for my purposes it's always more intuitive (for me) to use a regular collection or a simple counting variable.

This probably also just shows that there are more ways to approach something, and that it's also a matter of personal preference which approach to use.
The only idea I have after considering this is that if using ordinary int in this case, the problem would come up at real-time trading, cause the int m_counter would be recalculated on every tick, while you need it to be +1 after every bar that close is higher than given MA.
But I an not sure I am right here.

And if I am right here I then do not see the difference, why sometimes I have to use VariableObject and sometimes VariableSeries. Can not get it practical..

User avatar
JoshM
Posts: 2195
Joined: 20 May 2011
Location: The Netherlands
Has thanked: 1544 times
Been thanked: 1565 times
Contact:

Re: Real usage of VariableObject

Postby JoshM » 14 Mar 2016

The only idea I have after considering this is that if using ordinary int in this case, the problem would come up at real-time trading, cause the int m_counter would be recalculated on every tick, while you need it to be +1 after every bar that close is higher than given MA.
That's true, but I think that problem also happens with the `VariableObject<int>` here. That integer that's tied to the specific bar that's being evaluated by the script is also updated on every real-time tick. The difference is (from how I look at it) that there's no 'carryover effect': every bar there's a new object (int in this case) that's used with the calculations. However, if we use a single integer variable, we can of course reset that variable so there isn't a real problem that's solved by using `VariableObject<T>` here (from my understanding).

By the way, we can use `Bars.Status` (for the first data series) or `BarsOfData(x).Status` (for the xth data series) to check whether the script is calculated on bar close. That way the counter variable will be only incremented once per bar, for example:

Code: Select all

protected override void CalcBar()
{
double m_Avg = m_AverageFC[0];

if (Bars.Status == EBarState.Close && PublicFunctions.DoubleGreater(Price[0], m_Avg))
{
++m_Counter.Value;
}
else
{
m_Counter.Value = 0;
}

if (PublicFunctions.DoubleGreater(Bars.CurrentBar, ConfirmBars)
&& m_Counter.Value == ConfirmBars)
{
m_MACrossLE.Send();
}
}
(This same can also be done with a simple int counting variable, of course).

bobrovartiom
Posts: 8
Joined: 12 Mar 2016
Has thanked: 1 time

Re: Real usage of VariableObject

Postby bobrovartiom » 15 Mar 2016

That's true, but I think that problem also happens with the `VariableObject<int>` here. That integer that's tied to the specific bar that's being evaluated by the script is also updated on every real-time tick. The difference is (from how I look at it) that there's no 'carryover effect': every bar there's a new object (int in this case) that's used with the calculations. However, if we use a single integer variable, we can of course reset that variable so there isn't a real problem that's solved by using `VariableObject<T>` here (from my understanding).

By the way, we can use `Bars.Status` (for the first data series) or `BarsOfData(x).Status` (for the xth data series) to check whether the script is calculated on bar close. That way the counter variable will be only incremented once per bar, for example:

Code: Select all

protected override void CalcBar()
{
double m_Avg = m_AverageFC[0];

if (Bars.Status == EBarState.Close && PublicFunctions.DoubleGreater(Price[0], m_Avg))
{
++m_Counter.Value;
}
else
{
m_Counter.Value = 0;
}

if (PublicFunctions.DoubleGreater(Bars.CurrentBar, ConfirmBars)
&& m_Counter.Value == ConfirmBars)
{
m_MACrossLE.Send();
}
}
(This same can also be done with a simple int counting variable, of course).
Actually it seems that VariableObject solves exactly this problem if I understand the manual.

Here is the quote:
Those, who are familiar with C# or other OOP programming languages know such things as class fields.
Together they form the state of the object of the given class. In PL.NET there are special classes of variables
which make the writing logic of functions, indicators and signals easier regardless of whether the calculation
is executed based on historical or real-time data. When calculating a study on historical data, CalcBar()
method will be called once for each bar. This is an example of such a version of CurrentBar:
public class CurrentBar : FunctionSimple<int>

Code: Select all

{
public CurrentBar(CStudyControl master) : base(master){}
private int m_current_bar;
protected override int CalcBar(){
return ++m_current_bar;
}
protected override void StartCalc(){
36
m_current_bar = 0;
}
}
When calculating on historical data this function will return correct values only if it is called once per bar. In
real-time calculation, CalcBar will be called on each tick of bar, the function will not work correctly. To make
it work correctly, its logic should be changed. For example:

Code: Select all

protected override int CalcBar(){
var _result = m_current_bar + 1;
if (Bars.Status==EBarState.Close)
++m_current_bar;
return _result;
}
As we can see, the value of the variable has to be incremented only at the bar close. For these cases specific
variables exist: VariableSeries<T> and VariableObject<T>. VariableSeries<T> should be
used when it is necessary to call for the values of the previous bars variable. Considering this, the example
would look like this:
public class CurrentBar : FunctionSimple<int>

Code: Select all

{
public CurrentBar(CStudyControl master) : base(master){}
private VariableObject<int> m_current_bar;
protected override int CalcBar(){
return ++m_current_bar.Value;
}
protected override void Create(){
m_current_bar = new VariableObject<int>(this);
}
}
So they say here that if you want something to be calculated once a bar (not oftener) use the VariableObject.

Henry, or someone from Multicharts, is that right?

User avatar
Henry MultiСharts
Posts: 9165
Joined: 25 Aug 2011
Has thanked: 1264 times
Been thanked: 2957 times

Re: Real usage of VariableObject

Postby Henry MultiСharts » 06 Apr 2016

So they say here that if you want something to be calculated once a bar (not oftener) use the VariableObject.

Henry, or someone from Multicharts, is that right?
That is correct.


Return to “MultiCharts .NET”