Crashed in OnLoad with NotSupportedException: Unable to load unsupported parameter type
Crashed in OnLoad with NotSupportedException: Unable to load unsupported parameter type
23 May 2022, 21:04
Please, see the sample code below to replicate the issue. This used to work in the prior version of cTrader.
using cAlgo.API;
namespace cAlgo
{
[Indicator(AccessRights = AccessRights.None)]
public class UnsupportedParameterType : Indicator
{
[Output("Result")]
public IndicatorDataSeries Result { get; set; }
private Range _range;
protected override void Initialize()
{
_range = Indicators.GetIndicator<Range>(this);
}
public override void Calculate(int index)
{
Result[index] = _range.Result[index];
}
}
internal class Range : Indicator
{
[Parameter]
public UnsupportedParameterType Owner { get; set; }
[Output("Result")]
public IndicatorDataSeries Result { get; set; }
public override void Calculate(int index)
{
var bar = Bars[index];
Result[index] = bar.High - bar.Low;
}
}
}
Replies
amusleh
24 May 2022, 10:06
Hi,
The way you are using indicator parameters is not correct, it looks like it was working by luck and most probably it was a bug on version 4.1.
You can find the list of supported parameter types at: Indicator Code Samples - cTrader Automate API Documentation (spotware.github.io)
You can only use one of those types as a parameter.
@amusleh
Jiri
24 May 2022, 10:23
Hi @amusleh,
Thanks for the response. It appears to me that the prior version of cTrader was checking the parameter type only if the class was decorated with the IndicatorAttribute. This makes sense because of the rendering UI components. But if there is a non-public indicator used internally only, without the UI, why would it require the limited parameter type? It does not feel like this was a bug, everything was working as expected. Can you suggest a workaround to pass custom parameter types that would be assigned prior to the Initialize state?
@Jiri
amusleh
24 May 2022, 10:40
RE:
Jiri said:
Hi @amusleh,
Thanks for the response. It appears to me that the prior version of cTrader was checking the parameter type only if the class was decorated with the IndicatorAttribute. This makes sense because of the rendering UI components. But if there is a non-public indicator used internally only, without the UI, why would it require the limited parameter type? It does not feel like this was a bug, everything was working as expected. Can you suggest a workaround to pass custom parameter types that would be assigned prior to the Initialize state?
Hi,
It's definitely a bug on cTrader 4.2 that allows you to use not support parameter type.
You are using Parameter attribute in a way that is not meant to be used nor documented.
And you are also using GetIndicator incorrectly, it should only be used when you are using a referenced external indicator, not an indicator that resides on your current indicator assembly.
Regarding a solution, it's very simple, change your indicator design, use API members properly, why you need another indicator inside your current indicator assembly?
The problem you are trying to solve is you want to exchange data between two indicators, you can use static properties for it which is the simplest option.
If you need a sample check our Synchronized Indicators:
@amusleh
Jiri
24 May 2022, 10:53
RE: RE:
It's definitely a bug on cTrader 4.2 that allows you to use not support parameter type.
Why is it not supported anymore, what's the reason behind it? It's more like a hidden feature that was removed if anything.
You are using Parameter attribute in a way that is not meant to be used nor documented.
What are other ways of passing parameters to the indicator constructor if not by decorating it with ParameterAttribute and then passing it to the GetIndicator method?
And you are also using GetIndicator incorrectly, it should only be used when you are using a referenced external indicator, not an indicator that resides on your current indicator assembly.
What's the proper way of initializing internal indicators if not by using the GetIndicator?
Regarding a solution, it's very simple, change your indicator design, use API members properly, why you need another indicator inside your current indicator assembly?
Because there are relations between the objects, C# is an object-oriented programming language. Can you modify the sample code in the first post using the technique you are describing? I am failing to understand the solution you are proposing.
The problem you are trying to solve is you want to exchange data between two indicators, you can use static properties for it which is the simplest option.
I need to pass an object to an indicator in the constructor, using static variables is not acceptable.
@Jiri
amusleh
24 May 2022, 12:06
( Updated at: 24 May 2022, 12:18 )
Hi,
Why is it not supported anymore, what's the reason behind it? It's more like a hidden feature that was removed if anything.
It shouldn't be supported on the first place at all, you were able to use non supported parameter type because there was a bug on validation of indicator parameters that were initialized by GetIndicator method, and now it's fixed.
There is another similar case, in version 4.2 you can't access or call any API member from another thread, you have to use BeginInvokeOnMainThread method, due to this changes lots of indicators/cBots stopped working, but it was not a compatibility issue, it was a bug on 4.1 and it was fixed, we have stated several times on Automate API documentation that it's not thread safe but users continued to access the API members from other threads and it was working just by luck, now we have a check and it doesn't allow access from other threads.
What are other ways of passing parameters to the indicator constructor if not by decorating it with ParameterAttribute and then passing it to the GetIndicator method?
Indicator instances are created by API itself, you don't create an instance by calling the indicator constructor, so there is no way to pass an object to an indicator or cBot constructor, there was never such a feature and if you tried to find some hacks and it was working on version 4.1 there is no guarantee that it will continue to work.
You can't pass anything to an indicator or cBot before it's OnStart/Initialize method is called, this is a limitation of API and you should not try to find a workaround to bypass it.
You have to develop your cBots/Indicators by considering the API limitations, not by bypassing them.
What's the proper way of initializing internal indicators if not by using the GetIndicator?
What's an internal indicator? there should be no internal indicator, this is my first time I'm seeing an indicator inside another indicator assembly, GetIndicator method is for initializing referenced indicators not for creating new indicator class inside another indicator.
Because there are relations between the objects, C# is an object-oriented programming language. Can you modify the sample code in the first post using the technique you are describing? I am failing to understand the solution you are proposing.
I will change your design completely if it was on me I would not designed that indicator like that on the first place, you have to ask what you want to solve? what's the problem? then implement your solution based on limitations of your environment, what you did was a temporary hack the bypasses the environment limitations not solving the issue.
Indeed C# is an OOP language, but you are using a service that is not developed by you and it has it's own limitations.
Here is how I developed your indicator:
using cAlgo.API;
namespace cAlgo
{
[Indicator(AccessRights = AccessRights.None)]
public class UnsupportedParameterType : Indicator
{
[Output("Result")]
public IndicatorDataSeries Result { get; set; }
private Range _range;
protected override void Initialize()
{
_range = new Range(Bars);
}
public override void Calculate(int index)
{
Result[index] = _range.GetCalculationValue(index);
}
}
internal class Range
{
private readonly Bars _bars;
public Range(Bars bars)
{
_bars = bars;
}
public double GetCalculationValue(int index)
{
var bar = _bars[index];
return bar.High - bar.Low;
}
}
}
I need to pass an object to an indicator in the constructor, using static variables is not acceptable.
You can pass an object to another object via it's constructor if you are calling the constructor, you don't call the indicator/cBot constructor, then how you want to pass anything to it?
This is simple logic, I have developed a ton of cTrader indicators/cBots and I have never tried something that you did, it all depends on your software design and architecture skills.
The problem you are trying to solve is not passing objects to an indicator constructor, you want to send some data to another indicator instance, for that you have several options:
- Public properties
- Static data available on a separate class if you want to have access to the data during indicator initialization
Hopefully my words were useful for you.
@amusleh
Jiri
24 May 2022, 13:02
( Updated at: 24 May 2022, 14:22 )
Why is it not supported anymore, what's the reason behind it? It's more like a hidden feature that was removed if anything.
It shouldn't be supported on the first place at all, you were able to use non supported parameter type because there was a bug on validation of indicator parameters that were initialized by GetIndicator method, and now it's fixed.
You did not answer my question, why it should not be supported in the first place? Why is it marked as a bug?
What are other ways of passing parameters to the indicator constructor if not by decorating it with ParameterAttribute and then passing it to the GetIndicator method?
Indicator instances are created by API itself, you don't create an instance by calling the indicator constructor, so there is no way to pass an object to an indicator or cBot constructor, there was never such a feature and if you tried to find some hacks and it was working on version 4.1 there is no guarantee that it will continue to work.
You can't pass anything to an indicator or cBot before it's OnStart/Initialize method is called, this is a limitation of API and you should not try to find a workaround to bypass it.
You have to develop your cBots/Indicators by considering the API limitations, not by bypassing them.
The limitation wasn't there before so why is it introduced now? I would not call it a hack, but not going to argue about that because it's pointless.
What's the proper way of initializing internal indicators if not by using the GetIndicator?
What's an internal indicator? there should be no internal indicator, this is my first time I'm seeing an indicator inside another indicator assembly, GetIndicator method is for initializing referenced indicators not for creating new indicator class inside another indicator.
So you are saying there is no support for internal indicators anymore, right? Because this is what I am arguing about all the time - it was possible prior to 4.2! I didn't have to expose the indicator to the UI and had the freedom to work with the Indicator base class as I liked. There is no difference between having multiple indicators in a single assembly versus having them split into multiple assemblies except for accessibility which you have made unsupported with this "bug fix".
Because there are relations between the objects, C# is an object-oriented programming language. Can you modify the sample code in the first post using the technique you are describing? I am failing to understand the solution you are proposing.
I will change your design completely if it was on me I would not designed that indicator like that on the first place, you have to ask what you want to solve? what's the problem? then implement your solution based on limitations of your environment, what you did was a temporary hack the bypasses the environment limitations not solving the issue.
Indeed C# is an OOP language, but you are using a service that is not developed by you and it has it's own limitations.
Right, you are essentially going to functional programming and limiting OOP in this case. The code is just a sample to reproduce the issue, I bet you can imagine what it is going to be like to change complex projects utilizing the Indicator properties and functions by porting from the prior cTrader version to the current one like you did here.
To summarize it, please correct me if I am wrong. The cTrader 4.2 raised the limitations for unexplained reasons causing old algos that were working completely fine not to work anymore. These changes are marked as a bug fix for your convenience despite no issues experienced in the past and you are unwilling to take the limitation away in the upcoming version. So I am forced to redesign the majority of my indicators to follow the strict design pattern - not being able to use the Indicator base class internally with custom parameter types. Is that correct?
@Jiri
amusleh
25 May 2022, 09:29
( Updated at: 25 May 2022, 09:30 )
RE:
Hi,
You did not answer my question, why it should not be supported in the first place? Why is it marked as a bug?
It was never supported, parameter have a list of supported types, you can't use other types except them for parameters.
You are misusing parameter attribute, it's meant to be used for showing a parameter on indicator/cBot parameters window, it's linked to cTrader UI and you can't use any object you want to as a parameter.
This is and was our design, you can't blame us for your misuse of API.
The limitation wasn't there before so why is it introduced now? I would not call it a hack, but not going to argue about that because it's pointless.
It's not a new imposed limitation, it was a bug on parameter type validation and it's now fixed.
cTrader verifies if an indicator/cBot parameters are of supported types or not, because we can't show a UI for it.
So you are saying there is no support for internal indicators anymore, right? Because this is what I am arguing about all the time - it was possible prior to 4.2! I didn't have to expose the indicator to the UI and had the freedom to work with the Indicator base class as I liked. There is no difference between having multiple indicators in a single assembly versus having them split into multiple assemblies except for accessibility which you have made unsupported with this "bug fix".
I have no idea what's internal indicator, we never had such a thing, where you got the idea of creating a new indicator or robot class inside another indicator / cBot assembly? where it's documented? where you saw the GetIndicator method to be used for creating an indicator instance that is already inside the current indicator assembly?
What I'm not getting is why you create an indicator class? you don't have to, an indicator class is used for an indicator that is shown on cTrader and it's called by API, if you have some other services use another class like I showed you.
The way you used Parameter attribute was not correct, and you were exploiting a bug on parameter type validation.
Right, you are essentially going to functional programming and limiting OOP in this case. The code is just a sample to reproduce the issue, I bet you can imagine what it is going to be like to change complex projects utilizing the Indicator properties and functions by porting from the prior cTrader version to the current one like you did here.
I'm not going to argue about FP and OOP, I don't think those are related to our topic at all.
You have to use an API properly, if there was something weird possible you had to report it to us, not misuse it.
To summarize it, please correct me if I am wrong. The cTrader 4.2 raised the limitations for unexplained reasons causing old algos that were working completely fine not to work anymore. These changes are marked as a bug fix for your convenience despite no issues experienced in the past and you are unwilling to take the limitation away in the upcoming version. So I am forced to redesign the majority of my indicators to follow the strict design pattern - not being able to use the Indicator base class internally with custom parameter types. Is that correct?
We haven't imposed any new limitation, cTrader 4.2 contains some bug fixes, you were exploiting a bug on API and when it got fixed now you are complaining why we imposed new limitation?
@amusleh
Jiri
25 May 2022, 13:03
It was never supported, parameter have a list of supported types, and you can't use other types except them for parameters.
It was supported, how else would I build indicators that way which are working perfectly fine (prior 4.2) and are still used by hundreds of cTrader users.
You are misusing parameter attribute, it's meant to be used for showing a parameter on indicator/cBot parameters window, it's linked to cTrader UI and you can't use any object you want to as a parameter.
That applies to public indicators with IndicatorAttribute that are supposed to be shown in the UI, then it makes sense to have limited types supported only. If the indicator is not decorated with the IndicatorAttribute, whether it’s public, internal, or private, it is not exposed to the UI, and there is no need for the parameter type limitation. Using the ParameterAttribute is the only way to populate properties in the constructor by using the GetIndicator method and passing parameters into it. Which is how I built my indicators that were working for years without a single problem.
This is and was our design, you can't blame us for your misuse of API. The way you used Parameter attribute was not correct, and you were exploiting a bug on parameter type validation. You were exploiting a bug on API and when it got fixed now you are complaining why we imposed new limitation?
Are you serious about this?! I used the API as it was delivered to me. If I blame you for anything then it's for making changes for no reason that breaks almost every product I have made for this community and for you being so arrogant and unwilling to do anything about it.
I have no idea what's internal indicator
Here you can learn about internal modifier, what it is and why to use them. I have mentioned it numerous times, there are accessibility and OOP reasons for it. I don't see why I should be limiting myself to certain design patterns only.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/internal
It's not a new imposed limitation, it was a bug on parameter type validation and it's now fixed. You have to use an API properly, if there was something weird possible you had to report it to us, not misuse it. We haven't imposed any new limitation, cTrader 4.2 contains some bug fixes.
The limitation wasn't there before, it wasn't mentioned anywhere as a bug, and it wasn't breaking anything. If there is no reason for the change then why make it? I would really like to know what kind of bug this change is fixing. It breaks products that are in use by hundreds of users, it’s your community and my customers that are affected.
Please, revert this change and make the parameter type check only if the indicator is public and decorated with the IndicatorAttribute as it used to be all the time! Most of these indicators are offered for free so it's not worth my time to redesign all the indicators, reinvent the wheel to get all the features I am utilizing from the Indicator class, and redistribute it to over 600 users. If you don't want to address this, then let me know so I can inform all the users about discontinuing all the products before their brokers roll to the latest version of cTrader. I am already getting angry emails from those that have rolled over to the latest version.
@Jiri
amusleh
25 May 2022, 13:16
RE:
Hi,
We are not going to remove parameter type validation, you have to update your indicators / cBots.
Jiri said:
Here you can learn about internal modifier, what it is and why to use them. I have mentioned it numerous times, there are accessibility and OOP reasons for it. I don't see why I should be limiting myself to certain design patterns only.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/internal
I meant your internal indicator design not C# internal modifier.
@amusleh
Jiri
25 May 2022, 13:28
( Updated at: 25 May 2022, 13:38 )
I am not asking you to remove it, I am asking you to add the condition back in so my products can continue to work.
Please, can you explain why there needs to be the parameter type check for all the classes inheriting from the Indicator despite not being decorated with the IndicatorAttribute, why the change is required and can't be reverted?
@Jiri
jamesthedaytrader
26 May 2022, 01:16
RE:
Jiri said:
I am not asking you to remove it, I am asking you to add the condition back in so my products can continue to work.
Please, can you explain why there needs to be the parameter type check for all the classes inheriting from the Indicator despite not being decorated with the IndicatorAttribute, why the change is required and can't be reverted?
Please ctrader let’s have a work around for this. Do the community a favor here we would all appreciate it
@jamesthedaytrader
amusleh
27 May 2022, 09:07
RE: RE:
Jiri said:
amusleh said:
Hi,
We discussed this and we are considering to change this behavior, but we can't make any promise.
Any estimation on when will you know the final verdict? Is it considered in the upcoming version, if so what is the ETA?
hi,
We are considering to change this behavior back, I can't give you any ETA for now.
@amusleh
amusleh
31 May 2022, 11:12
RE:
Jiri said:
Hi! Any update? Is this a high priority? There are many users worried at this point, please give me something that I can use to calm them down and ensure it will be working again in the near future.
Hi,
It's high priority and this change will take effect on future releases of cTrader, I can't give you any exact ETA but you can expect it on next couple of weeks.
@amusleh
Jiri
31 May 2022, 12:57
RE: RE:
amusleh said:
Jiri said:
Hi! Any update? Is this a high priority? There are many users worried at this point, please give me something that I can use to calm them down and ensure it will be working again in the near future.
Hi,
It's high priority and this change will take effect on future releases of cTrader, I can't give you any exact ETA but you can expect it on next couple of weeks.
Glad to hear that, much appreciated!
@Jiri
amusleh
24 May 2022, 09:57
Hi,
We were able to reproduce the issue, we will investigate and update you soon.
@amusleh