Pinescript: Enter position when multiple conditions are met but one is bool type and other is float - crossover

I am fairly new and can sure use your kind help.
Trying to validate a standard MACD crossover to generate a buy signal ONLY IF the following average directional movement function (which can show only 0 or 1 values), displays in the previous trading day a "1" value.
//ADX Oscillator
[di_pos, di_neg, adx] = ta.dmi(14, 14)
SellLong = ta.change(adx) > 0 ? true : false
Idea is to validate the MACD crossover (buy signal) only if it happens after a "strong" selloff, highlighted by high ADX. My problem is that strategy execution condition (as follows) returns exception for comparing float with bool type data.
if ta.crossover(delta, 0) and SellLong [1]=1
strategy.entry ()
Thanks a lot
A

Related

Pine Script Issue Percentage Change

I am trying to create a normalized percentage change script on the interaday charts, identical to the percent setting when clicking the bottom left gear button and then clicking "percent" in the tradingview chart, allowing the user to compare two securities accumulated price movement expressed in terms of percentages on any given timeframe in this case I am using duration of only 1 day with 1 minute bars. In python it would be similar to the .rebase() function or .pct_change() function.
My Current Issues
The first is that the percentage return being returned from the script does not replicate the percentage return shown on the graph for SPY.(Although the shape of the SPY indicator line generated by the script does match the SPY line just that the value as shown in the below pictures does not match.)
My script does not start at some indexed (ie. normalized value) lets say 0% when including another security to the script. To explain my issue easily I have only included one security within the code below for this post.
CODE
First Attempt using the ta.change() function
//Using the change() function
//#version=5
indicator("var float accum_base", format = format.percent, overlay=false)
// Add the script's inputs
symb3 = input.symbol(title="SPY", defval="AMEX:SPY")
//Retrieve Symbol Price Data
SPY = request.security(symb3, timeframe.period, close)
//Percentage Change Calc
change = ta.change(SPY, 1) / SPY[1]
//acum method to accumulate all percentage changes from first bar
var float accum = na
accum := nz(accum + change)
plot(accum)
Using the ta.change() function script SPY returns -0.12% vs the displayed SPY return of -1.66%
Second Attempt using the ta.roc() function
//#version=5
indicator("roc function", format = format.percent, overlay=false)
// Add the script's inputs
symb3 = input.symbol(title="SPY", defval="AMEX:SPY")
//Retrieve Symbol Price Data
SPY = request.security(symb3, timeframe.period, close)
//Percentage Change Calc
base = ta.roc(SPY, 1) / SPY
//Acummulated Percentage Change
var float accum_base = na
accum_base := nz(accum_base + base)
plot(accum_base, title= "SPY", color=color.purple)
Second attempt using the ta.roc function the script SPY returns -0.03% vs the displayed SPY return of -1.66%
I have tried everything and could not resolve the issue. Any help would be greatly appreciated!

Provide a list of numbers to Alexa

I want to create a lottery skill that takes 6 numbers from the user.
I'm currently learning by going through the samples and developer guides, and I can go through the guides and get a working skill that will take one input and then end the session. But I believe I need to create a dialog somehow, which is where I get stuck.
Design-wise, I'd like the dialog to go like this:
Alexa: Please provide the first number
User: 1
Alexa: and now the second...
User: 2
etc etc
But I think it would be OK if it went like this:
Alexa: Please call out 6 numbers
User: 1, 2, 3, 4, 5, 6.
Is this even possible? Will I have to create a custom slot type called "Numbers" and then put in the numbers, eg 1-50 or whatever the limit is?
At best, I can currently get it to ask for one number, so its really the dialog interaction that I'm stuck on. Has anyone ever even done anything like this?
Thanks.
Yes to both questions. You could string together a response with 6 different custom slots. "User: My numbers are {num1}, {num2}, {num3}, {num4}, {num5}, {num6} " and make them all required using the skills beta developer. However, it will be a rather bad user experience if the user does not phrase their answer appropriately and Alexa has to ask follow up questions to obtain each number. The last problem you'll run into is that while a custom slot could be defined to contain the numbers 1-50 alexa will generally recognize similar values to those provided in a custom slot, such as numbers from 50-99. It would then be up to you to check that the values you receive are between 1 and 50. If not you'd want to ask the user to provide a different number in the appropriate range.
Conclusion: You'll want to have individual interactions where a user provides a single number at a time.
Alexa:"you will be prompted for 6 numbers between 1 and 50 please state them one at a time. Choose your first number."
User:"50"
Alexa:"Your First number is 50, Next number."...
You can implement this using a single intent. let's name that intent GetNumberIntent. GetNumberIntent will have sample uterances along the line of
{number}
pick {number}
choose {number}
where {number} is a custom slot type or simply AMAZON.NUMBER. It will then be up to you to check that the number is between 1 and 50.
I program in Node.js using the SDK. Your implementation may vary depending upon your language choice.
What I would do is define 6 different state handlers. Each handler should have the GetNumberIntent. When a GetNumberIntent is returned if the slot value is apropriate store the value to the session data and or dynamodb and move forward to the next state. If the slot value is invalid stay for example at state "NumberInputFiveStateHandlers" until a good value is received then change state to the next "NumberInputSixStateHandlers"
var NumberInputFiveStateHandlers = Alexa.CreateStateHandler(states.NUMFIVEMODE, {
'NewSession': function () {
this.emit('NewSession'); // Uses the handler in newSessionHandlers
},
//Primary Intents
'GetNumberIntent': function () {
let message = ` `;
let reprompt = ` `;
let slotValue = this.event.request.intent.slots.number.value;
if(parseInt(slotValue) >= 1 && parseInt(slotValue) <= 50){
this.handler.state = states.NUMSIXMODE;
this.attributes['NUMBERFIVE'] = this.event.request.intent.slots.number.value;
message = ` Your fifth number is `+slotValue+`. please select your sixth value. `;
reprompt = ` please select your sixth value. `;
}else{
message = ` The number `+slotValue)+` is not in the desired range between 1 and 50. please select a valid fifth number. `;
reprompt = ` please select your fifth value. `;
}
this.emit(':ask',message,reprompt);
},
//Help Intents
"InformationIntent": function() {
console.log("INFORMATION");
var message = ` You've been asked to choose a lottery number between 1 and 50. Please say your selection.`;
this.emit(':ask', message, message);
},
"AMAZON.StopIntent": function() {
console.log("STOPINTENT");
this.emit(':tell', "Goodbye!");
},
"AMAZON.CancelIntent": function() {
console.log("CANCELINTENT");
this.emit(':tell', "Goodbye!");
},
'AMAZON.HelpIntent': function() {
var message = `You're playing lottery. you'll be picking six numbers to play the game. For help with your current situation say Information. otherwise you may exit the game by saying quit.`;
this.emit(':ask', message, message);
},
//Unhandled
'Unhandled': function() {
console.log("UNHANDLED");
var reprompt = ' That was not an appropriate response. Please say a number between 1 and 50.';
this.emit(':ask', reprompt, reprompt);
}
});
This is an example of the fifth request. You'll have 6 identical states like this one that string back to back. Eventually you'll end up with 6 session values.
this.attributes['NUMBERONE']
this.attributes['NUMBERTWO']
this.attributes['NUMBERTHREE']
this.attributes['NUMBERFOUR']
this.attributes['NUMBERFIVE']
this.attributes['NUMBERSIX']
You can then use these values for your game.
If you have not used the alexa-sdk before you must remember to register your state handlers and add your modes to the states variable.
alexa.registerHandlers(newSessionHandlers, NumberInputOneStateHandlers, ... NumberInputSixStateHandlers);
var states = {
NUMONEMODE: '_NUMONEMODE',
...
...
NUMSIXMODE: '_NUMSIXMODE',
}
This answer is not intended to cover the basics of coding using Alexas-SDK. There are other resourced for more specific questions on that topic.
Alternatively, because your intent is identical [GetNumberIntent], you may be able to get by with a single StateHandler that pushes new valid numbers onto an array until the array is the desired length. That would simply require more logic inside the Intent Handler and a conditional to break out of the state once the array is of length 6.
Try the code above first because it's easier to see the different states.

reductio Max of a sum

I have a dataset I'm working with that is buildings and electrical power use over time.
There are two aggregations on these buildings that are simple sums across the entire timespan and I have those written. They end up looking like:
var reducer = reductio();
// How much energy is used in the whole system
reducer.value("energy").sum(function (d) {
return +d.Energy;
});
These work great.
The third aggregation, however, is giving me some trouble. I need to find the point that the sum of all the buildings is at its greatest. I need the max of the sum and the time it happened.
I wrote:
reducer.value("power").sum(function (d) {
return +d.Power;
}).max(function (d) {
return +d.Power;
}).aliasProp({
time: function (d, v) {
return v.Timestamp;
}
});
But, this is not necessarily the biggest power use. I'm pretty sure this returns the sum and the time when any individual building used the most power.
So if the power values were 1, 1, 1, 15. I would end up with 18, when there might be a different moment when the values were 5, 5, 5, 5 for a total of 20. The 20 is what I need.
I am at a loss for how to get the maximum of a sum. Any advice?
Just to restate: You are grouping on time, so your group keys are time periods of some sort. What you want is to find the time period (group) for which power use is greatest.
If I'm right that this is what you want, then you would not do this in your reducer, but rather by sorting the groups. You can order groups by using the group.order method: https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_order
// During group setup
group.order(function(p) { return p.power.sum; })
// Later, when you want to grab the top power group
group.top(1)
Reductio's max aggregation should just give you the maximum value that occurs within the group. So given a group with values 1,1,1,15, you would get back the value 15. It sounds like that's not what you want.
Hopefully I understood properly. If not, please comment. If you can put together an example with toy data that is public and where you can tell me what you would like to see vs what you are getting, I should be able to help out.
Update based on example:
So, what you want (based on the description in the example) is to find the maximum power usage for any given time within the selected time period. So you would do the following:
var timeDim = buildings.dimension(function(d) { return d.Timestamp })
var timeGrp = timeDim.group().reduceSum(function(d) { return d.Power })
var maxResults = timeGrp.top(1)
Whenever you want to find the max power usage time for your current filter, just call timeGrp.top(1) and the key of that group will be the time with the maximum power.
Note: Don't filter on timeDim as the filters on a dimension are not applied to groups defined on that dimension.
Here's an updated JSFiddle that writes out the maximum group to the console: https://jsfiddle.net/esjewett/1o3robm3/1/

math.random and corona incorrect syntax?

I've been doing this for 2 days and getting nowhere.
I want to select 4 balls from the array and randomly drop them, but for the system to remeber and ask for input later.
I'm stuck on the first bit:
local ballImages =
{
display.newImage("ball1.png"),
display.newImage("ball2.png"),
display.newImage("ball3.png"),
display.newImage("ball4.png"),
display.newImage("ball5.png"),
display.newImage("ball6.png"),
display.newImage("ball7.png"),
display.newImage("ball8.png"),
display.newImage("ball9.png"),
display.newImage("ball10.png"),
display.newImage("ball11.png"),
display.newImage("ball12.png"),
display.newImage("ball13.png"),
display.newImage("ball14.png"),
display.newImage("ball15.png"),
display.newImage("ball16.png"),
display.newImage("ball17.png"),
display.newImage("ball18.png"),
display.newImage("ball19.png"),
display.newImage("ball20.png")
}
function setup()
math.randomseed(os.time())
end
setup()
local ballImages = ballImages[math.random(4,#ballImages)]
physics.addBody(ballImages)
I'm only getting 1 ball to randomly drop. Do I have the syntax in math.random wrong?
Ive tried it several ways but not sure where to go from here.
Thanks in advance for help!
Yes, the syntax is wrong. See http://docs.coronalabs.com/api/library/math/random.html :
When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].
You should make 4 calls to math.random(#ballImages).
If you just want 4 balls, possibly more than once the same ball, you're done.
However if you want distinct balls, you may have to redraw, if you draw a number that corresponds to a ball selected previously. That is if two of your math.random(#ballImages) return the same number i, that would mean "dropping the ball" i twice. If that doesn't make sense, you can do something like the following :
drawn = {}
local drop=4 -- how many balls to draw
while drop > 0 do -- while we have balls left to draw
local ball = math.random(#ballImages) -- draw a random ball
if drawn[ball] == nil then -- if ball wasn't selected before
drawn[ball] = 1 -- mark it as selected
physics.addBody(ballImages[ball]) -- "drop" the ball
drop = drop - 1 -- decrement how many more balls
end
end
If your display and physics objects work, then so should this snippet. See here : http://ideone.com/GQC2C6

Oscillate value based on input

Math is not my strong suit; hope to find some help for this pretty basic question. I have a function taking an input value based on a modulus operation. So the input goes from 0-60, then repeats. I want the function to return an value that oscillates within a range. For example, it would return values in the range 0-60, then return values in the range 60-0, then repeat.
Can anyone point me in the right direction?
Edit Here is what my function to look like:
int convert(int input) {
// input = 0...1...2... 60...0...1...
// return= 0...1...2... 60...59...58...
}
Assuming I understand what you want, the simplest answer would be to return input * 2 if input is less than or equal to 30 and 120 - input * 2 if the input is greater. This will give you a triangular output for a linearly-increasing input.

Resources