ternary operator ?: is throwing errors about wrong arguments - if-statement

I'm trying to display a different time frame macd on a given time frame chart. so display 5 min macd on 1 min chart etc.
I've decided to accomplish that by multiplying a number 5 to the interval which is an integer and then turn that into a string and use that in the plot.
This works fine since I don;'t have to change it every time I change the time frame of the chart from 1 to 10 min etc, and it will still display the longer time frame macd based on the multiple.
This following code works fine using the ternary operator ?:
//#version = 2
study(title="test")
source = close
fastLength = input(12, minval=1)
slowLength=input(26,minval=1)
signalLength=input(9,minval=1)
// res5 mutiplies the current interval which is an integer by a factor 5 and turns it into a string with the value of "interval*5" or "1D" depending on the value of interval*5
res5= interval*5 < 1440 ? tostring(interval*5) : "1D"
src5=security(tickerid, res5, close)
fastMA5 = ema(src5, fastLength)
slowMA5 = ema(src5, slowLength)
macd5 = fastMA5 - slowMA5
signal5 = sma(macd5, signalLength)
outMacD5 = security(tickerid, res5, macd5)
plot( outMacD5 ? outMacD5 : na, color= red)
But if I were to change it to have more conditions like below, the ternary operator fails.
//#version = 2
study(title="test")
source = close
fastLength = input(12, minval=1)
slowLength=input(26,minval=1)
signalLength=input(9,minval=1)
// res5 mutiplies the current interval which is an integer by a factor 5 and turns it into a string with the value of "interval*5" or "1D" depending on the value 9of inteval*5
//res5= interval*5 < 1440 ? tostring(interval*5) : "1D"
res5= interval*5 < 1440 ? tostring(interval*5) : interval >= 1440 and interval*5 < 2880 ? "1D":na
src5=security(tickerid, res5, close)
fastMA5 = ema(src5, fastLength)
slowMA5 = ema(src5, slowLength)
macd5 = fastMA5 - slowMA5
signal5 = sma(macd5, signalLength)
outMacD5 = security(tickerid, res5, macd5)
plot( outMacD5 ? outMacD5 : na, color= red)
That brings back the error
Add to Chart operation failed, reason: Error: Cannot call `operator ?:` with arguments (bool, literal__string, na); available overloads ...
Using the iff brings back the same error about the arguments being incorrect.
I could really use some help here. I'm so lost in using these conditional operators.
Any tips are helpful.

Use this:
res5= interval*5 < 1440 ? tostring(interval*5) : interval >= 1440 and interval*5 < 2880 ? "1D": ""
plotchar(res5=="5", "res5 test", "", location=location.top)
The plotchar() call will allow you to confirm res5's value. Here it is being tested for "5", so you will be able to verify in the Data Window (doesn't print anything in the indicator's pane so it doesn't disturb scale) that its value is 1 -> true when you are on a 1min chart.
[Edit 2019.08.19 09:02 — LucF]
Your question was about the ternary not working, which the code above resolves. Following your comment, you also need a more complete function to calculate a multiple of the current timeframe in v2. Use this:
f_MultipleOfRes( _mult) =>
// Convert target timeframe in minutes.
_TargetResInMin = interval * _mult * (
isseconds ? 1. / 60. :
isminutes ? 1. :
isdaily ? 1440. :
isweekly ? 7. * 24. * 60. :
ismonthly ? 30.417 * 24. * 60. : na)
// Find best way to express the TF.
_TargetResInMin <= 0.0417 ? "1S" :
_TargetResInMin <= 0.167 ? "5S" :
_TargetResInMin <= 0.376 ? "15S" :
_TargetResInMin <= 0.751 ? "30S" :
_TargetResInMin <= 1440 ? tostring(round(_TargetResInMin)) :
tostring(round(min(_TargetResInMin / 1440, 365))) + "D"
See here for a use case, but don't use that function code as it's v4.

Related

Issue with the ternary statement

<cfscript>
x = 100;
y = 1;
var i = len(x) ? ((y == 1) ? 'PD': 'PP') : 'PU'
dump(i);
</cfscript>
problem is it is coming as PD while it should come as PP
If i am running in this gist, it works, only in my actual code it is behaving odd,
the values are not coming from anywhere else i double checked it
possibly if i write it in another way, that might fix it, any way i can do it
Ternary logic is essentially "if my condition is true, then do this, else do that.
<cfscript>
x = 100;
y = 1;
var i = len(x) ? ((y == 1) ? 'PD': 'PP') : 'PU'
dump(i);
</cfscript>
As written, what you have is:
"If there is a length of x, then ( if y is 1 then 'PD', else 'PP' ), else 'PU'.
Step 1: len(x) >>> x is the number 100, but is converted to the string "100", whose length is 3. But since ternary is a conditional, len(x) is true. So 'PU' can't be the answer.
Step 2: y == 1 >>> another conditional. And since you've set y to 1, then that is also true. So the answer will be the first part, or 'PD'.
Step 3: i is set to 'PD', as per the above ternary operations.
The answer you are getting is correct.

How do I go about getting the real result for 50%60 in C++

I please check this problem I'm creating a Time Base app but I'm having problem getting to work around the modulus oper (%) I want the remainder of 50%60 which I'm expecting to output 10 but it just give me the Lhvalues instead i.e 50. How do I go about it.
Here is a part review of the code.
void setM(int m){
if ((m+min)>59){
hour+=((min+m)/60);
min=0;
min=(min+m)%60;
}
else min+=m;
}
In the code m is passed in as 50 and min is passed in as 10
How do I get the output to be 10 for min in this equation min=(min+m)%60; without reversing the equation i.e
60%(min+m)
in C++ expression a % b returns remainder of division of a by b (if they are positive. For negative numbers sign of result is implementation defined).
you should do : 60 % 50 if you want to divide by 50
Or, if you want to get mins, i think you don't need to make min=0.
When you do 50 % 60, you get a remiainder of 50 since 50 cannot be divided by 60.
To get around this error, you can try doing do something like 70 % 60 to get the correct value as a result, since you do not want to use 60 % 50
This would follow the following logic:
Find the difference between 60 and min + m after min is set to zero if min + mis less than 60. Store it in a variable var initially set to zero.
check if the result is negative; if it is, then set it to positive by multiplying it by -1
When you do the operation, do min = ((min + m) + var) % 60; instead.
***Note: As I am unfamiliar with a Time Base App and what its purpose is, this solution may or may not be required, hence please inform me in the comments before downvoting if I there is anything wrong with my answer. Thanks!
It looks like you are trying to convert an integral number of minutes to an hour/minute pair. That would look more like this instead:
void setM(int m)
{
hour = m / 60;
min = m % 60;
}
If you are trying to add an integral number of minutes to an existing hour/minute pair, it would look more like this:
void addM(int m)
{
int value = (hour * 60) + min;
value += m;
hour = value / 60;
min = value % 60;
}
Or
void addM(int m)
{
setM(((hour * 60) + min) + m);
}

How to check if a value within a range is multiple of a value from another range?

Let say I've a system that distribute 8820 values into 96 values, rounding using Banker's Round (call them pulse). The formula is:
pulse = BankerRound(8820 * i/96), with i[0,96[
Thus, this is the list of pulses:
0
92
184
276
368
459
551
643
735
827
919
1011
1102
1194
1286
1378
1470
1562
1654
1746
1838
1929
2021
2113
2205
2297
2389
2481
2572
2664
2756
2848
2940
3032
3124
3216
3308
3399
3491
3583
3675
3767
3859
3951
4042
4134
4226
4318
4410
4502
4594
4686
4778
4869
4961
5053
5145
5237
5329
5421
5512
5604
5696
5788
5880
5972
6064
6156
6248
6339
6431
6523
6615
6707
6799
6891
6982
7074
7166
7258
7350
7442
7534
7626
7718
7809
7901
7993
8085
8177
8269
8361
8452
8544
8636
8728
Now, suppose the system doesn't send to me these pulses directly. Instead, it send these pulse in 8820th (call them tick):
tick = value * 1/8820
The list of the ticks I get become:
0
0.010430839
0.020861678
0.031292517
0.041723356
0.052040816
0.062471655
0.072902494
0.083333333
0.093764172
0.104195011
0.11462585
0.124943311
0.13537415
0.145804989
0.156235828
0.166666667
0.177097506
0.187528345
0.197959184
0.208390023
0.218707483
0.229138322
0.239569161
0.25
0.260430839
0.270861678
0.281292517
0.291609977
0.302040816
0.312471655
0.322902494
0.333333333
0.343764172
0.354195011
0.36462585
0.375056689
0.38537415
0.395804989
0.406235828
0.416666667
0.427097506
0.437528345
0.447959184
0.458276644
0.468707483
0.479138322
0.489569161
0.5
0.510430839
0.520861678
0.531292517
0.541723356
0.552040816
0.562471655
0.572902494
0.583333333
0.593764172
0.604195011
0.61462585
0.624943311
0.63537415
0.645804989
0.656235828
0.666666667
0.677097506
0.687528345
0.697959184
0.708390023
0.718707483
0.729138322
0.739569161
0.75
0.760430839
0.770861678
0.781292517
0.791609977
0.802040816
0.812471655
0.822902494
0.833333333
0.843764172
0.854195011
0.86462585
0.875056689
0.88537415
0.895804989
0.906235828
0.916666667
0.927097506
0.937528345
0.947959184
0.958276644
0.968707483
0.979138322
0.989569161
Unfortunately, between these ticks it sends to me also fake ticks, that aren't multiply of original pulses. Such as 0,029024943, which is multiply of 256, which isn't in the pulse lists.
How can I find from this list which ticks are valid and which are fake?
I don't have the pulse list to compare with during the process, since 8820 will change during the time, so I don't have a list to compare step by step. I need to deduce it from ticks at each iteration.
What's the best math approch to this? Maybe reasoning only in tick and not pulse.
I've thought to find the closer error between nearest integer pulse and prev/next tick. Here in C++:
double pulse = tick * 96.;
double prevpulse = (tick - 1/8820.) * 96.;
double nextpulse = (tick + 1/8820.) * 96.;
int pulseRounded=round(pulse);
int buffer=lrint(tick * 8820.);
double pulseABS = abs(pulse - pulseRounded);
double prevpulseABS = abs(prevpulse - pulseRounded);
double nextpulseABS = abs(nextpulse - pulseRounded);
if (nextpulseABS > pulseABS && prevpulseABS > pulseABS) {
// is pulse
}
but for example tick 0.0417234 (pulse 368) fails since the prev tick error seems to be closer than it: prevpulseABS error (0.00543795) is smaller than pulseABS error (0.0054464).
That's because this comparison doesn't care about rounding I guess.
NEW POST:
Alright. Based on what I now understand, here's my revised answer.
You have the information you need to build a list of good values. Each time you switch to a new track:
vector<double> good_list;
good_list.reserve(96);
for(int i = 0; i < 96; i++)
good_list.push_back(BankerRound(8820.0 * i / 96.0) / 8820.0);
Then, each time you want to validate the input:
auto iter = find(good_list.begin(), good_list.end(), input);
if(iter != good_list.end()) //It's a match!
cout << "Happy days! It's a match!" << endl;
else
cout << "Oh bother. It's not a match." << endl;
The problem with mathematically determining the correct pulses is the BankerRound() function which will introduce an ever-growing error the higher values you input. You would then need a formula for a formula, and that's getting out of my wheelhouse. Or, you could keep track of the differences between successive values. Most of them would be the same. You'd only have to check between two possible errors. But that falls apart if you can jump tracks or jump around in one track.
OLD POST:
If I understand the question right, the only information you're getting should be coming in the form of (p/v = y) where you know 'y' (that's each element in your list of ticks you get from the device) and you know that 'p' is the Pulse and 'v' is the Values per Beat, but you don't know what either of them are. So, pulling one point of data from your post, you might have an equation like this:
p/v = 0.010430839
'v', in all the examples you've used thus far, is 8820, but from what I understand, that value is not a guaranteed constant. The next question then is: Do you have a way of determining what 'v' is before you start getting all these decimal values? If you do, you can work out mathematically what the smallest error can be (1/v) then take your decimal information, multiply it by 'v', round it to the nearest whole number and check to see if the difference between its rounded form and its non-rounded form falls in the bounds of your calculated error like so:
double input; //let input be elements in your list of doubles, such as 0.010430839
double allowed_error = 1.0 / values_per_beat;
double proposed = input * values_per_beat;
double rounded = std::round(proposed);
if(abs(rounded - proposed) < allowed_error){cout << "It's good!" << endl;}
If, however, you are not able to ascertain the values_per_beat ahead of time, then this becomes a statistical question. You must accumulate enough data samples, remove the outliers (the few that vary from the norm) and use that data. But that approach will not be realtime, which, given the terms you've been using (values per beat, bpm, the value 44100) it sounds like realtime might be what you're after.
Playing around with Excel, I think you want to multiply up to (what should be) whole numbers rather than looking for closest pulses.
Tick Pulse i Error OK
Tick*8820 Pulse*96/8820 ABS( i - INT( i+0.05 ) ) Error < 0.01
------------ ------------ ------------- ------------------------ ------------
0.029024943 255.9999973 2.786394528 0.786394528 FALSE
0.0417234 368.000388 4.0054464 0.0054464 TRUE
0 0 0 0 TRUE
0.010430839 91.99999998 1.001360544 0.001360544 TRUE
0.020861678 184 2.002721088 0.002721088 TRUE
0.031292517 275.9999999 3.004081632 0.004081632 TRUE
0.041723356 367.9999999 4.005442176 0.005442176 TRUE
0.052040816 458.9999971 4.995918336 0.004081664 TRUE
0.062471655 550.9999971 5.99727888 0.00272112 TRUE
0.072902494 642.9999971 6.998639424 0.001360576 TRUE
0.083333333 734.9999971 7.999999968 3.2E-08 TRUE
The table shows your two "problem" cases (the real wrong value, 256, and the one your code gets wrong, 368) followed by the first few "good" values.
If both 8820s vary at the same time, then obviously they will cancel out, and i will just be Tick*96.
The Error term is the difference between the calculated i and the nearest integer; if this less than 0.01, then it is a "good" value.
NOTE: the 0.05 and 0.01 values were chosen somewhat arbitrarily (aka inspired first time guess based on the numbers): adjust if needed. Although I've only shown the first few rows, all the 96 "good" values you gave show as TRUE.
The code (completely untested) would be something like:
double pulse = tick * 8820.0 ;
double i = pulse * 96.0 / 8820.0 ;
double error = abs( i - floor( i + 0.05 ) ) ;
if( error < 0.05 ) {
// is pulse
}
I assume your initializing your pulses in a for-loop, using int i as loop variable; then the problem is this line:
BankerRound(8820 * i/96);
8820 * i / 96 is an all integer operation and the result is integer again, cutting off the remainder (so in effect, always rounding towards zero already), and BankerRound actually has nothing to round any more. Try this instead:
BankerRound(8820 * i / 96.0);
Same problem applies if you are trying to calculate prev and next pulse, as you actually subtract and add 0 (again, 1/8820 is all integer and results in 0).
Edit:
From what I read from the commments, the 'system' is not – as I assumed previously – modifiable. Actually, it calculates ticks in the form of n / 96.0, n &#x220a [0, 96) in ℕ
however including some kind of internal rounding appearently independent from the sample frequency, so there is some difference to the true value of n/96.0 and the ticks multiplied by 96 do not deliver exactly the integral values in [0, 96) (thanks KarstenKoop). And some of the delivered samples are simply invalid...
So the task is to detect, if tick * 96 is close enough to an integral value to be accepted as valid.
So we need to check:
double value = tick * 96.0;
bool isValid
= value - floor(value) < threshold
|| ceil(value) - value < threshold;
with some appropriately defined threshold. Assuming the values really are calculated as
double tick = round(8820*i/96.0)/8820.0;
then the maximal deviation would be slightly greater than 0.00544 (see below for a more exact value), thresholds somewhere in the sizes of 0.006, 0.0055, 0.00545, ... might be a choice.
Rounding might be a matter of internally used number of bits for the sensor value (if we have 13 bits available, ticks might actually be calculated as floor(8192 * i / 96.0) / 8192.0 with 8192 being 1 << 13 &ndash and floor accounting to integer division; just a guess...).
The exact value of the maximal deviation, using 8820 as factor, as exact as representable by double, was:
0.00544217687075132516838493756949901580810546875
The multiplication by 96 is actually not necessary, you can compare directly with the threshold divided by 96, which would be:
0.0000566893424036596371706764330156147480010986328125

Adding constraints for a known solution causes out of bounds exception

I have a linear optimization goal to Maximize EE+FF, where EE and FF each consist of some C and D.
With code I've written, I can get solver to find:
EE_quantity: 0, FF_quantity: 7
...but I know there to be another solution:
EE_quantity: 1, FF_quantity: 6
In order to validate user input for other valid solutions, I added a constraint for both EE and FF. So I added the EE_quantity == 0, FF_quantity == 7 in the code below, which is a runnable example:
SolverContext c2 = SolverContext.GetContext();
Model m2 = c2.CreateModel();
p.elements = elements_multilevel_productmix();
Decision C_quantity = new Decision(Domain.IntegerNonnegative, "C_quantity");
Decision D_quantity = new Decision(Domain.IntegerNonnegative, "D_quantity");
Decision EE_quantity = new Decision(Domain.IntegerNonnegative, "EE_quantity");
Decision FF_quantity = new Decision(Domain.IntegerNonnegative, "FF_quantity");
m2.AddDecisions(C_quantity, D_quantity, EE_quantity, FF_quantity);
m2.AddConstraints("production",
6 * C_quantity + 4 * D_quantity <= 100,
1 * C_quantity + 2 * D_quantity <= 200,
2 * EE_quantity + 1 * FF_quantity <= C_quantity,
1 * EE_quantity + 2 * FF_quantity <= D_quantity,
EE_quantity == 0,
FF_quantity == 7
);
m2.AddGoal("fixed_EE_FF", GoalKind.Maximize, "EE_quantity + FF_quantity");
Solution sol = c2.Solve(new SimplexDirective());
foreach (var item in sol.Decisions)
{
System.Diagnostics.Debug.WriteLine(
item.Name + ": " + item.GetDouble().ToString()
);
}
It seems that Solver Foundation really doesn't like this specific combination. Using EE_quantity == 1, FF_quantity == 6 is fine, as is using just EE_quantity == 0 or FF_quantity == 7. But using both, AND having one of them being zero, throws an exception:
Index was outside the bounds of the array.
What is going on under the hood, here? And how do I specify that I want to find "all" solutions for a specific problem?
(Note: no new releases of Solver Foundation are forthcoming - it's essentially been dropped by Microsoft.)
The stack trace indicates that this is a bug in the simplex solver's presolve routine. Unfortunately the SimplexDirective does not have a way to disable presolve (unlike InteriorPointDirective). Therefore the way to get around this problem is to specify the fixed variables differently.
Remove the last two constraints that set EE_quantity and FF_quantity, and instead set both the upper and lower bounds to be 0 and 7 respectively when you create the Decision objects. This is equivalent to what you wanted to express, but appears to avoid the MSF bug:
Decision EE_quantity = new Decision(Domain.IntegerRange(0, 0), "EE_quantity");
Decision FF_quantity = new Decision(Domain.IntegerRange(7, 7), "FF_quantity");
The MSF simplex solver, like many mixed integer solvers, only returns the optimal solution. If you want MSF to return all solutions, change to the constraint programming solver (ConstraintProgrammingDirective). If you review the documentation for Solution.GetNext() you should figure out how to do this.
Of course the CP solver is not guaranteed to produce the globally optimal solution immediately. But if you iterate through solutions long enough, you'll get there.

What is rolling sum and how to impliment it in Informatica and my requirement is as follows?

Can someone pl tell me what is rolling sum and how to implement it in Informatica?
My requirement is as below:(Given by client)
ETI_DUR :
SUM(CASE WHEN AGENT_EXPNCD_DIM.EXCEPTION_CD='SYS/BLDG ISSUES ETI' THEN IEX_AGENT_DEXPN.SCD_DURATION ELSE 0 END)
ETI_30_DAY :
ROLLING SUM(CASE WHEN (SYSDATE-IEX_AGENT_DEXPN.ROW_DT)<=30 AND AGENT_EXPNCD_DIM.EXCEPTION_CD = 'SYS/BLDG ISSUES ETI'
THEN IEX_AGENT_DEXPN.SCD_DURATION ELSE 0 END)
ETI_30_DAY_OVRG :
CASE WHEN ETI_DUR > 0 THEN
CASe
WHEN ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 29 DAYS) BETWEEN 0 AND 600 AND ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 29 DAYS) + ETI_DUR > 600 THEN ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 30 DAYS) - 600
WHEN ROLLINGSUM(ETI_DUR_30_DAY FOR LAST 29 DAYS) > 600 THEN ETI_DUR
ELSE 0 END
ELSE 0 END
And i have implemented as below in Informatica.
Expression Transformation:
o_ETI_DUR-- IIF(UPPER(EXCEPTION_CD_AGENT_EXPNDIM)='SYS/BLDG ISSUES ETI',SCD_DURATION,0)
o_ETI_29_DAY-- IIF(DATE_DIFF(TRUNC(SYSDATE),trunc(SCHD_DATE),'DD') <=29 AND UPPER(EXCEPTION_CD_AGENT_EXPNDIM) = 'SYS/BLDG ISSUES ETI' ,SCD_DURATION,0)
o_ETI_30_DAY -- IIF(DATE_DIFF(TRUNC(SYSDATE),trunc(SCHD_DATE),'DD') <=30 AND UPPER(EXCEPTION_CD_AGENT_EXPNDIM) = 'SYS/BLDG ISSUES ETI' ,SCD_DURATION,0)
Aggregator transformation:
o_ETI_30_DAY_OVRG:
IIF(sum(i_ETI_DUR) > 0,
IIF((sum(i_ETI_29_DAY)>=0 and sum(i_ETI_29_DAY)<=600) and (sum(i_ETI_29_DAY)+sum(i_ETI_DUR)) > 600,
sum(i_ETI_30_DAY) - 600,
IIF(sum(i_ETI_29_DAY)>600,sum(i_ETI_DUR),0)),0)
But is not working. Pl help ASAP.
Thanks a lot....!
Rolling sum is just the sum of some amount over a fixed duration of time. For example, everyday you can calculate the sum of expense for last 30 days.
I guess you can use an aggregator to calculate ETI_DUR, ETI_30_DAY and ETI_29_DAY. After that, in an expression you can implement the logic for ETI_30_DAY_OVRG. Note that you cannot write an IIF expression like that in an aggregator. Output ports must use an aggregate function.
Here is a rolling sum example:
count, rolling_sum
1,1
2,3
5,8
1,9
1,10
Basically it is the sum of the values listed previously. To implement it in Informatica use 'local variables' (variable port in expression transformation) as follows:
input port: count
variable port: v_sum_count = v_sum_count + count
output port: rolling_sum = v_sum_count
we have a moving sum function defined in Numerical functions in Expression transformation:
MOVINGSUM(n as numeric, i as integer, [where as expression]).
Please check if it helps.