Support Board
Date/Time: Wed, 27 Nov 2024 10:43:47 +0000
[Programming Help] - Code help, using a string instead of a constant
View Count: 619
[2023-08-27 13:37:30] |
j4ytr4der_ - Posts: 938 |
I'm modifying some open source code (from https://gcuserstudies.github.io/) but have run into a problem I've been unable to figure out how to solve. I'm sure this should be ridiculously simple but I've been at this for days and can't figure it out. There is some code that evaluates a formula. It works fine for a single iteration, but I want it to execute in a (manual) loop of all the available inputs. This is a problem because the original loop uses a constant ( const char* ) and so the loop can't modify it each time. I've tried using an SCString instead but then the value of the formula gets mangled and doesn't appear to execute properly.In abbreviated form, here's the code that "works" in the loop of inputs, but the value of the constant never changes once it's set the first time. ParseAndSetFormula = sc.IsFullRecalculation; const char* Formula = sc.Input[InputIndex].GetString(); // Grab the formula for the chosen input double FormulaOutput = sc.EvaluateGivenAlertConditionFormulaAsDouble(BarIndex, ParseAndSetFormula, Formula); // Evaluate the formula sc.Subgraph[InputIndex][BarIndex] = (float)FormulaOutput; // Return the formula result in a subgraph I've tried changing const char* Formula to SCString Formula but it doesn't work. I've also tried just using char rather than const char but that won't even compile.I know slightly more than nothing about C++ so I'm fairly sure I'm probably missing something really simple/obvious to someone who knows what they're doing. Can anyone point me in the right direction here? |
[2023-08-27 15:18:48] |
ondafringe - Posts: 286 |
I don't know enough to help you, other than to say: I think this char* formula; creates a pointer called "formula" It doesn't create a variable called "formula" and you can't assign a value to a pointer like this const char* Formula = sc.Input[InputIndex].GetString(); like you would to a variable. So you might want to do some digging into c++ pointers. |
[2023-08-27 17:37:23] |
User431178 - Posts: 544 |
and you can't assign a value to a pointer like this
Sorry, but that is not correct, look at what the return type is for GetString.@j4ytr4der_ and so the loop can't modify it each time
That doesn't seem right either.Is InputIndex the loop variable? I am assuming you are declaring Formula inside the loop If Formula is decalred in loop then it goes out of scope at the end of each loop. Please post additional code (or send via private message if you prefer). Date Time Of Last Edit: 2023-08-27 19:53:31
|
[2023-08-27 18:26:09] |
ondafringe - Posts: 286 |
Then explain so we can all learn something. If char* Formula creates a pointer to a memory address holding char-type data, then if sc.Input[InputIndex].GetString(); returns something like "&charvar" I can see how that would be valid, otherwise... And to reference the value a pointer is pointing to, or pass that value as an argument like double FormulaOutput = sc.EvaluateGivenAlertConditionFormulaAsDouble(BarIndex, ParseAndSetFormula, Formula); don't you also have to preface it like so? *Formula
Because Formula
would only return the memory address the pointer is pointing to. Date Time Of Last Edit: 2023-08-27 20:07:40
|
[2023-08-27 18:51:06] |
j4ytr4der_ - Posts: 938 |
So yes, InputIndex is the loop counter. Formula is (attempting to be) defined at each repetition of the loop. I posted everything relevant I'm pretty sure, but here's the whole loop. bool ParseAndSetFormula = sc.IsFullRecalculation; for(int InputIndex = 1; InputIndex <= 16; InputIndex++) // Loop through each input { const char* Formula = sc.Input[InputIndex].GetString(); // Grab the formula for the chosen input for (int BarIndex = sc.UpdateStartIndex; BarIndex < sc.ArraySize; BarIndex++) { double FormulaOutput = sc.EvaluateGivenAlertConditionFormulaAsDouble(BarIndex, ParseAndSetFormula, Formula); // Evaluate the formula sc.Subgraph[InputIndex][BarIndex] = (float)FormulaOutput; // Return the formula result in a subgraph } } Date Time Of Last Edit: 2023-08-27 19:11:58
|
[2023-08-27 20:12:42] |
j4ytr4der_ - Posts: 938 |
Nope, using *Formula generates a CPU exception.
|
[2023-08-27 20:14:09] |
j4ytr4der_ - Posts: 938 |
And again, the const char* DOES pick up the value of the input string as expected, but only the first time. Then it's there permanently since it's a constant, so every single subgraph after the first one parsed, gets the same result.
|
[2023-08-27 20:32:52] |
ondafringe - Posts: 286 |
I'm looking at this link for pointers: https://www.programiz.com/cpp-programming/pointers But, yeah, this is pretty confusing stuff. lol However, maybe the reason you are only getting the first formula is because you are trying to redeclare a const within the for loop. I don't believe that is allowed, unless you first drop out of the for loop. Have you tried declaring Formula like this, leaving const out: char* Formula I just looked at sc.EvaluateGivenAlertConditionFormulaAsDouble and it does show "const SCString& Formula" as the third argument, so the above probably won't work. Date Time Of Last Edit: 2023-08-27 20:46:36
|
[2023-08-27 20:54:43] |
User431178 - Posts: 544 |
And again, the const char* DOES pick up the value of the input string as expected, but only the first time.
As I said before, const char* goes out of scope at the end of each iteration of the main loop, 100% guaranteed it is reading the value of the other inputs.The attached code works as expected (sligtly modified from what you posted), see also screenshot. |
alert formula string.png / V - Attached On 2023-08-27 20:54:29 UTC - Size: 74.25 KB - 111 views AlertString.cpp - Attached On 2023-08-27 20:54:38 UTC - Size: 1.6 KB - 162 views |
[2023-08-27 21:10:15] |
ondafringe - Posts: 286 |
As I said before, const char* goes out of scope at the end of each iteration of the main loop
Had no idea. Could have sworn it stayed in scope. Learned something new. :) Still doesn't explain the pointer confusion because it doesn't seem to jive with what I read at that pointer link. Date Time Of Last Edit: 2023-08-27 21:14:00
|
[2023-08-27 21:17:38] |
j4ytr4der_ - Posts: 938 |
char* Formula won't compile. I'll try the posted code and see what's changed, thanks!
|
[2023-08-27 21:28:50] |
j4ytr4der_ - Posts: 938 |
OK, the attached code works so I just need to work it into mine. Thanks, will post a link to it once it's working!
|
[2023-08-27 22:39:46] |
j4ytr4der_ - Posts: 938 |
One question as this doesn't make sense to me. You made a small change to the final return of the value to a subgraph, that code is now: sc.Subgraph[InputIndex][BarIndex] = (float)FormulaOutput * (InputIndex + 1); // Return the formula result in a subgraph
You added * (InputIndex + 1)
What is the significance of that? Seems weird to me to multiply whatever the final result is, by the number of the current input plus 1. |
[2023-08-28 01:12:46] |
j4ytr4der_ - Posts: 938 |
Also I have to correct what I said before, the posted code does not work. It doesn't generate any errors, but it definitely doesn't work properly. I can enter the simple formula 1+1 and (after enabling display of name & values) the subgraph will flash to 2 for a moment, then back to zero. I can put in H, L, C, etc. and the same happens. It flashes the correct value for a moment, then goes to zero.
|
[2023-08-28 01:16:33] |
j4ytr4der_ - Posts: 938 |
Actually on closer inspection, it's not even showing the correct values at all. Looking at ES where price is currently around 4430, and it's showing OHLC prices between 4000 and 17000. In fact each subgraph goes progressively higher, and if I fill all 4 with O H L and C, the values don't flash back to zero and I can see all of them. https://snipboard.io/jwxJh8.jpg Date Time Of Last Edit: 2023-08-28 01:18:06
|
[2023-08-28 08:47:20] |
User431178 - Posts: 544 |
What is the significance of that? Seems weird to me to multiply whatever the final result is, by the number of the current input plus 1.
The purpose of that was to make the visual representation of each formula result easier to distinguish in the image that was attached, i.e. cleary show that each formula was there were being evaluated. The demo image had 4 formula set, each yielding a true/false (1.0/0.0) output, rather than display all at 1.0, the results were adjusted to display the result of each at a different value. Adding 1 to the input index is necessary as the inputs are indexed from 0. Input 1: 1.0 * (0 + 1) = 1.0 Input 2: 1.0 * (1 + 1) = 2.0 etc... Outside of what I wanted to demonstrate, the * (InputIndex + 1) part serves no purpose - remove it. See attached image with offending code removed. |
formula string ohlc.png / V - Attached On 2023-08-28 08:46:57 UTC - Size: 86.23 KB - 80 views |
[2023-08-28 09:02:18] |
User431178 - Posts: 544 |
The previously attached code served to demonstrate that what you were trying to do was possible, however it does not work correctly for live updating. For live updating to work correctly, you will need to parse and set each formula again at each chart update. If the parse/set is not done, only the last set formula is used. Updated code attached. I should add that setting the formula at each update goes against the advice in the docs (inefficient), however I don't see an alternative. Date Time Of Last Edit: 2023-08-28 09:02:46
|
AlertString.cpp - Attached On 2023-08-28 09:02:14 UTC - Size: 1.58 KB - 177 views |
[2023-08-28 15:39:36] |
j4ytr4der_ - Posts: 938 |
The problem I'm raising with your example code isn't about not updating live, it's that the initial values are completely nonsensical. Put something in all 4 formulas, specifically O, H, L, and C. I get values that make absolutely no sense.
|
[2023-08-28 16:00:03] |
j4ytr4der_ - Posts: 938 |
OK now that I understand what that extra multiplication you added was about, removing it has corrected the behavior I was seeing. Thanks, I should be able to work with this.
|
[2023-08-28 16:29:00] |
j4ytr4der_ - Posts: 938 |
I have it working for historical bars, but I can't get it to work for the current updating bar. As far as I understand it should be calculating correctly for all bars up to the last one but for some reason it isn't. Don't know what I'm missing. #include "sierrachart.h" SCDLLName("Multi Formula All Bars") /*==================================================================================*/ SCSFExport scsf_TestProj(SCStudyInterfaceRef sc) { sc.MaintainVolumeAtPriceData = 1; if (sc.SetDefaults) { sc.GraphName = "Multi Formula All Bars"; sc.GraphRegion = 2; sc.AutoLoop = 0; sc.ValueFormat = VALUEFORMAT_INHERITED; sc.ScaleRangeType = SCALE_AUTO; sc.GlobalDisplayStudySubgraphsNameAndValue = 1; sc.DisplayStudyInputValues = 0; sc.HideDLLAndFunctionNames = 1; for (auto i = 0; i < 4; ++i) { sc.Input[i].Name.Format("s%d", i); sc.Input[i].SetString(""); sc.Subgraph[i].Name.Format("s%d", 1); sc.Subgraph[i].DrawStyle = DRAWSTYLE_POINT; sc.Subgraph[i].LineWidth = 4; } return; } bool ParseAndSetFormula = sc.IsFullRecalculation; for (int InputIndex = 0; InputIndex < 4; InputIndex++) // Loop through each input { const char* Formula = sc.Input[InputIndex].GetString(); // Grab the formula for the chosen input for (int BarIndex = sc.UpdateStartIndex; BarIndex < sc.ArraySize; BarIndex++) { double FormulaOutput{ 0.0 }; if (BarIndex == 0) FormulaOutput = sc.EvaluateGivenAlertConditionFormulaAsDouble(BarIndex, ParseAndSetFormula, Formula); // Evaluate the formula else FormulaOutput = sc.EvaluateGivenAlertConditionFormulaAsDouble(BarIndex, 0, ""); // Evaluate the formula sc.Subgraph[InputIndex][BarIndex] = (float)FormulaOutput; // Return the formula result in a subgraph } } } |
[2023-08-28 16:47:44] |
User431178 - Posts: 544 |
I have it working for historical bars, but I can't get it to work for the current updating bar. As far as I understand it should be calculating correctly for all bars up to the last one but for some reason it isn't. Don't know what I'm missing.
Please see the second code example posted above. this bool ParseAndSetFormula = sc.IsFullRecalculation;
andif (BarIndex == 0) FormulaOutput = sc.EvaluateGivenAlertConditionFormulaAsDouble(BarIndex, ParseAndSetFormula, Formula); // Evaluate the formula else FormulaOutput = sc.EvaluateGivenAlertConditionFormulaAsDouble(BarIndex, 0, ""); // Evaluate the formula Mean that the formula are parsed and set only during a full recalculation and only at bar index 0. As you are cycling through various formula, you will need to parse and set each time, otherwise only the last set formula is applied. |
[2023-08-28 17:00:13] |
j4ytr4der_ - Posts: 938 |
Ah of course, I forgot about IsFullRecalculation. Got it now, thanks.
|
To post a message in this thread, you need to log in with your Sierra Chart account: