I am in the process of building a somewhat complex building block.
The names and types of building block variables depend on the parameter settings of this block.
If a parameter change leads (for example) to a change of an int variable to a double variable, the resulting strategy code does not compile.
Here is a minimal working example of a Condition Block:
Run this with "Use Integer" the first time.
Then switch to "Use Floating Point" and run again.
This will result in a compile error.
Possible Reason
The store behind RegisterVariable() is not cleared before the next run.
A variable with the same name (but different type) is still in this store and generated code is wrong.
Possible Solution
Clear the store behind RegisterVariable() before a new C# Strategy is generated.
The names and types of building block variables depend on the parameter settings of this block.
If a parameter change leads (for example) to a change of an int variable to a double variable, the resulting strategy code does not compile.
Here is a minimal working example of a Condition Block:
CODE:
using WealthLab.Backtest; using WealthLab.Core; namespace DemoBlock { public class DemoBlock : ConditionBuildingBlock { public override string Name => "DemoBlock"; public override void GenerateParameters() { AddParameter("Choice", ParameterType.StringChoice, "Use Integer") .Choices = new List<string> { "Use Integer", "Use Floating Point" }; } public override void GenerateVarCode() { if (Parameters[0].AsString == "Use Integer") RegisterVariable("myVar", "int"); else RegisterVariable("myVar", "double"); base.GenerateVarCode(); } public override void GenerateInitCode() { if (Parameters[0].AsString == "Use Integer") InitCode.Add("\t<myVar> = 42;"); else InitCode.Add("\t<myVar> = 3.141;"); } public override void GenerateConditionCode() { if (Parameters[0].AsString == "Use Integer") MainCode.Add("if(<myVar> > 12)"); else MainCode.Add("if(<myVar> < 0.9)"); } } }
Run this with "Use Integer" the first time.
Then switch to "Use Floating Point" and run again.
This will result in a compile error.
Possible Reason
The store behind RegisterVariable() is not cleared before the next run.
A variable with the same name (but different type) is still in this store and generated code is wrong.
Possible Solution
Clear the store behind RegisterVariable() before a new C# Strategy is generated.
Rename
It should work for you in Build 100.
I have a similar problem with AddToUsingClause().
For reasons explained above I need to call AddToUsingClause() not from Initialize() but from GenerateVarCode() instead.
If done so, the using statement appears for the second run of "Open as C# Coded Strategy" and a "Run Backtest" results (always) in an error.
(Everything works nicely if I move the AddToUsingClause() to Initialize(), which is ok for a test, but does not help for the final version of my Condition Block)
For reasons explained above I need to call AddToUsingClause() not from Initialize() but from GenerateVarCode() instead.
If done so, the using statement appears for the second run of "Open as C# Coded Strategy" and a "Run Backtest" results (always) in an error.
(Everything works nicely if I move the AddToUsingClause() to Initialize(), which is ok for a test, but does not help for the final version of my Condition Block)
Can’t you just always add any possible libraries to the using clause in Initialize? You’re starting to push this design beyond what it was intended to support.
QUOTE:
You’re starting to push this design beyond what it was intended to support.
I consider Building Blocks as a fantastic way to create complex trading strategies with low effort.
The Blocks allow to generate complex C# code that is otherwise very hard to produce.
It might be the case, that the Building Blocks were originally thought to allow some simple Buy/Sell Strategies. But I recognize this concept as a much more general code generation facility.
And we are almost there.
QUOTE:
Can’t you just always add any possible libraries to the using clause in Initialize?
Not really.
One of the parameters of my Condition Building Block contains an Indicator Expression for the Eval indicator.
Depending on the indicators used in this expression, several usings are required.
In fact, if a new indicator extension shows up, a new using is required (probably after my block was compiled, purchased and delivered.)
So, what that Block does: It analyses what indicators are used, figures which using are required and adds these using to the generated code, even if the indicator and the usings are not known today...
Ok then we’ll need to add a #FeatureRequest to this topic.
Your Response
Post
Edit Post
Login is required