Pinescript - Syntax error at input 'else' - if-statement

I am having an issue with pinescript. Never used it before and havent coded in years so im very rusty.
I would love an opinion of why I am getting the error on line 21, which is the only 'else if' line in the block.
//#version=4
tradeDirection = input(direction.up, "Trade Direction") // direction of the breakout (up or down)
breakoutPeriod = input(14, "Breakout Period") // number of bars to look back for the breakout
stopLoss = input(0.002, "Stop Loss") // stop loss in percentage of the trade value
takeProfit = input(0.004, "Take Profit") // take profit in percentage of the trade value
maxTrades = input(2, "Maximum Number of Trades") // maximum number of trades to have open at the same time
maxRisk = input(0.01, "Maximum Risk per Trade") // maximum risk per trade in percentage of the account value
// Next, we create a variable to track the highest or lowest price in the breakout period
breakoutPrice = tradeDirection == direction.up ? highest(high, breakoutPeriod) : lowest(low, breakoutPeriod)
// Then, we check if the current price has broken out of the breakout period and if we have not reached the maximum number of open trades
if (tradeDirection == direction.up and close > breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a long position with the calculated trade size
strategy.entry("Long", strategy.long, tradeSize)
else if (tradeDirection == direction.down and close < breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a short position with the calculated trade size
strategy.entry("Short", strategy.short, tradeSize)
// Finally, we set our stop loss and take profit levels
strategy.exit("Stop Loss", "Long", stopLossType.percent, stopLoss)
strategy.exit("Take Profit", "Long", profitType.percent, takeProfit)
// We repeat the same process for the short position
strategy.exit("Stop Loss", "Short", stopLossType.percent, stopLoss)
strategy.exit("Take Profit", "Short", profitType.percent, takeProfit)
I've looked around at other versions to see if its just a version issue but nothing that gives me a reaosn why its erroring out.
I get the feeling its something before or within the else if statement.

I retyped your script so it would compile and have no warnings or errors. One problem was the indentation was missing on the if and else. Another problem was the direction.up variable was missing. It is not allowed to have a . in a variable name. Another problem was that strategy("breakout strat") was missing, so I added it. The logic in the code I typed is probably wrong, but there are no errors.
//#version=4
strategy("breakout strat")
tradeDirection = input(true, "Trade Direction") // direction of the breakout (up=true or down=false)
breakoutPeriod = input(14, "Breakout Period") // number of bars to look back for the breakout
stopLoss = input(0.002, "Stop Loss") // stop loss in percentage of the trade value
takeProfit = input(0.004, "Take Profit") // take profit in percentage of the trade value
maxTrades = input(2, "Maximum Number of Trades") // maximum number of trades to have open at the same time
maxRisk = input(0.01, "Maximum Risk per Trade") // maximum risk per trade in percentage of the account value
// Next, we create a variable to track the highest or lowest price in the breakout period
breakoutPrice = tradeDirection == true ? highest(high, breakoutPeriod) : lowest(low, breakoutPeriod)
// Then, we check if the current price has broken out of the breakout period and if we have not reached the maximum number of open trades
if (tradeDirection == true and close > breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a long position with the calculated trade size
strategy.entry("Long", strategy.long, tradeSize)
else if (tradeDirection == false and close < breakoutPrice and strategy.opentrades < maxTrades)
// If it has, we calculate the trade size based on the maximum risk per trade
tradeSize = maxRisk / (stopLoss * close)
// And enter a short position with the calculated trade size
strategy.entry("Short", strategy.short, tradeSize)
// Finally, we set our stop loss and take profit levels
strategy.exit("Stop Loss", "Long", loss=stopLoss)
strategy.exit("Take Profit", "Long", loss=takeProfit)
// We repeat the same process for the short position
strategy.exit("Stop Loss", "Short", loss=stopLoss)
strategy.exit("Take Profit", "Short", loss=takeProfit)

Put an indentation on line 21 to get rid of this error :
if .....
----> First block
else if
----> Other block
In your code other indentations are missing, and other error are present (direction.up doesn't exist for example... but you should ask another question for another error)

Related

Can't understand how it works (ThinkScript code)

I'm currently converting a ThinkScript indicator to python, however, I've run into this piece of code and I'm kinda confused on how it works:
input rollingPeriodMinutes = 60;
def factor = (SecondsFromTime(Market_Open_Time) / (60 * rollingPeriodMinutes) / 100);
def rolloverTime = if factor == Round(factor) then 1 else 0;
rec H1 = compoundValue(1, if !rolloverTime then if high > H1[1] then high else H1[1] else high, high);
rec H = compoundValue(1, if rolloverTime then H1[1] else H[1], high);
I can't really understand what is stored at the end in the variable "H". Can you help me understand?
Any help is really appraciated!! Thanks
input rollingPeriodMinutes = 60;
declares (defines) and sets a variable, rollingPeriodMinutes, to a default value of 60. The input declaration indicates that the user will be able to alter this value in the thinkorswim settings for this script.
def factor = (SecondsFromTime(Market_Open_Time) / (60 * rollingPeriodMinutes) / 100);
declares and sets a variable, factor to a calculated value. This uses the rollingPeriodMinutes value, above, as well as the SecondsFromTime function and a Market_Open_Time variable that must have been set elsewhere in the script.
def rolloverTime = if factor == Round(factor) then 1 else 0;
declares and sets a variable, rolloverTime to a boolean based on the if statement. This uses the factor variable above (1 is true and 0 is false in thinkscript).
rec H1 = compoundValue(1, if !rolloverTime then if high > H1[1] then high else H1[1] else high, high);
rec H = compoundValue(1, if rolloverTime then H1[1] else H[1], high);
rec is actually the same as def and has been obsoleted. Previously, it specifically declared a recursive variable; now one would just use def regardless. See the notes below for more information.
CompoundValue is an easy statement in thinkscript, but complicated to understand from the Learning Center reference.
In short, the declarations for H and H1 are saying 'going back 1 bar: if no data is present, then use the if statement to determine a value; else if data is present, then use the high value.
Broken out, the algorithm for H1 (where high is a reserved word for the high price for a given bar) could look like:
let numBarsBack = 1
if (data is present for the bar at numBarsBack) then
if (!rolloverTime == true) then
if high > (H1 value one bar previous) then H1 = high
else H1 = (H1 value one bar previous)
else H1 = high // thinkscript sometimes requires a "default" in `if` statements, even if there's no 3rd possible value
else (if rolloverTime == true) then H1 = high
else (if data is not present for the bar at numBarsBack) then H1 = high
*** See my complete description of how CompoundValue works in thinkscript at the SO question "Understanding & Converting ThinkScripts CompoundValue Function".***
Notes:
SecondsFromTime, according to the current thinkscript Learning Center reference looks like:
SecondsFromTime ( int fromTime);
Description
Returns the number of seconds from the specified time (24-hour clock notation) in the EST timezone. Note that this function always returns zero when chart's aggregation period is greater than or equal to 1 day.
Input parameters
Parameter Default value Description
fromTime - Defines time from which seconds are counted, in the HHMM format, 24-hour clock notation.
The Learning Center reference for rec says this:
rec
Notice: this is an article about an obsolete thinkScript® notation. Although rec variables are still supported by thinkScript®, they can be completely replaced by def.
Syntax
rec
Description
Enables you to reference a historical value of a variable that you are calculating in the study or strategy itself. Rec is short for "recursion".
Example
rec C = C[1] + volume;
plot CumulativeVolume = C;
This example plots the cumulative volume starting from the beginning of the time period.
and, finally:
Remember that thinkscript code is executed for every bar in a selected period. Ie, if you're looking at 10 days with a daily period, there will be a bar for each of the 10 days; and the script will run a loop, repeating the code for each of those 10 bars. As a result, the variables will have appropriate values for each bar.
Although the OP is wanting to convert a script to Python, if someone comes here interested in how thinkscript works, there are tricks to keep a value constant for an entire script (though this section of code does not include examples for that). For information on how to do this in thinkscript, see my answer to SO question "thinkscript - How to create a variable that retains its value".

Calculate value using proportion

I'm designing a machine that requires an automated ignition system. This project uses a motor control script that I wrote for Arduino.
I need to calculate the delay between ignition based on the percentage motor load.
These are the variables currently used
//Variables
int potentiometerIn; //RAW Potentiometer data variable
int potentiometerIn2; //Used in percent calculation, Will be == to potentiometerIn, just a different operation order
int potentiometerDivper; //Variable to hold percentage calculation (first step)
int potentiometerPer; // Holds the integer percent for motor speed IE: motor at 83% speed would have this value at 83
int potentiometerDiv;
int motorPin = (); //REPLACE () with PIN NUM
int motorRly = (); //Motor Positive pin () = pin num + Motor Pin
int motorNeg = (); //Motor Negative Pin () = pin num (Likely Not Needed)
int igniteRly = (); //Ignition Control Positive Pin
int igniteNeg = (); //Ignition Control Negative Pin (Likely Not Needed)
int ignitionTime = 0; // This will be used to set the time for an electric ignition.
int ignitionCalc = (); //This should be the time in seconds, that it takes for the machine to complete a full cycle with the motor set to 50%
// This enables/disables the ignition portion
int ignitionEnabled = true; // Default = True
if (ignitionEnabled == true)
{
ignitionCalc * 1000; //Converts the seconds to a format accepted by delay
50 / ignitionCalc = potentiometerPer / ignitionTime;
}
A quick summary for those who don't want to read all of my comments (I'm writing this code before the motor arrives so the values are all unset)
potentiometerPer > This is the percentage of power being supplied to the motor.
ignitionTime > This value will be used to set the delay between ignition firing
ignitionCalc > The amount of time in seconds for 1 cycle at 50% power.
I'm trying to figure out a way to calculate the delay for ignition with regards to what percentage the motor is currently set to. For example:
If motor percentage is 80 and the time per cycle is 5, then at 100% power the time per cycle is X (in this case 6.25)
I can't seem to figure out how to do proportions in C++, I'm rather new to the language and only started to learn it for this project.
Well since when the motor power is at 80%, the time per cycle you get is 5. So ignore the percentage, lets just say that when power level is 80, you get time per cycle as 5. Ratios in simpler words are just divisions. When 80 is divided by 16, you get 5. So what we know is the value 16 is going to remain constant. Similarly if you take any value of motor power, and divide by 16, you are going to get what you want. If this ratio is going to remain constant then it will be for all cases no matter what the motor power is. Im assuming that the ratio is going to remain constant.
So what you can do is -
float timePerCycle = potentiometerPer/16;

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

a lot of decimal value storage in C++

I wanted to write a program that returns how many months we could survive when we're given
our monthly expenditure, amount of disposable income, and interest rate (all in integers).
For instance, if we start with disposable income = 1000, interest rate = 5%, monthly expenditure = 100, then
after first month: 1000*1.05 - 100 = 950, we have 950 dollars left
after second month: = 950*1.05 - 100 = 897.5
and so on, and in the end, we can survive 14 months.
I wrote the following code in C++:
int main(){
int i=0;
int initialValue;
int interest;
int monthly;
double value=1.0*initialValue;
double r=1+1.0*interest/100;
while(value > 0){
if(value < monthly){
break;
}
else
{
value=value*r-monthly;
i++;
}
};
cout<<i;
return 0;
}
but for sufficiently large values of initialValue and small values of monthly, the program I wrote runs very slowly to the degree that it's unusable. Is there a problem with the code that makes it run not well (or very slow)?
Any help would be greatly appreciated.
double cannot store numbers precisely. One consequence of this is when you subtract a very small number from a very large number, the result is not changed from the original large value.
One solution to this problem is to use an int to do your calculations. Think of the values as the number of pennies, rather than the number of dollars.
A few notes:
The *1.0's are pointless. Instead, take advantage of implicit and explicit casts:
double value=initialValue;
double r=1+(double)interest/100;
++i is faster than i++.
value=value* can be rewritten as value*=.
You can mix the first two conditionals. Remove the if...break and change the while loop to while (value > 0 && value < monthly).
On the face of it, the reason this runs slowly is the large number of iterations. However, you didn't specify any specific numbers and I would expect this code to be able to execute at least a million iterations per second on any reasonably fast processor. Did you really expect to need to calculate more than 1 million months?
Apart from the novice style of the code, the underlying problem is the algorithm. There are very simple formulae for making these calculations, which you can find here: https://en.wikipedia.org/wiki/Compound_interest. Your situation is akin to paying off a loan, where running out of money equals loan paid off.

Operations with structures, code not working?

Assume you are given three variables, revenue, expenses, and profit, all of type Money (a structured type with two int fields, dollars and cents). Assign to profit the result of subtracting expenses from revenue. Let's make the happy assumption that revenue exceeds expenses. However you still may find that the cents part of expenses exceeds that of revenue. If that is the case you will have to "borrow" 1 from revenue dollars (i.e. subtract 1) and "give" it to revenue's cents (i.e. add 100!) in order to carry out the subtraction properly.
Here is what I have but it's not working:
if (revenue.cents < expenses.cents)
{
revenue.dollars = revenue.dollars -1;
revenue.cents = revenue.cents + 100;
profit = revenue - expenses;
}
else
{
profit = revenue - expenses;
}
I get this error message:
error: no match for 'operator-' in 'revenue - expenses'
Any help is appreciated. Thanks.
You're getting that error because you cannot subtract one structure from another. You will have to define an operator-() function for your struct.
You need to call each element of the structure and subtract them separately. MyProgLab will not allow you to define a function for this exercise. Not only that but if you enter the code that you have above it will tell you that 'you were not supposed to modify the element'. In order to avoid this you must conduct the borrowing of the dollar inside the arithmetic.
Like this:
if(expenses.cents > revenue.cents)
{
profit.dollars = (revenue.dollars - 1) - expenses.dollars;
profit.cents = (revenue.cents + 100) - expenses.cents;
}//end if