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!
Related
this might look simple.. but dk how to do it
this is the information:
So.. i got the Cumulative Total using this function:
CumulativeTotal = CALCULATE(
SUM(vnxcritical[Used Space GB]),
FILTER(ALL(Datesonly[Date]),
Datesonly[Date] <= MAX(Datesonly[Date])))
But what i need is to get the differences between the dates, in the first date and the second the difference will be of 210. I need to get another column with that information. know the formula to do that?
ok..
So.. i used this:
IncrmentalValueTEST =
VAR CurrDate = MAX(vnxcritical[Date])
VAR PrevDate = CALCULATE(LASTDATE(vnxcritical[Date]), vnxcritical[Date] < CurrDate)
RETURN SUM(vnxcritical[Used Space GB]) -
CALCULATE(SUM(vnxcritical[Used Space GB]), vnxcritical[Date] = PrevDate)
and this is the result:
Ok, so this is is my data table:
You can see all the dates that i have for now, this is a capacity report for diferents EMC Storage Arrays, for diferentes Pools. The idea would be to have the knolwdge to review the incremental space used in a determinated portion of time.
allready tried another idea to get this, but the result was the same.. i used this:
Diferencia =
Var Day = MAX(Datesonly[Month])
Var Month = MAX(Datesonly[Year])
RETURN
SUM('Used Space'[used_mb])
- CALCULATE(
SUM('Used Space'[used_mb])
,FILTER(ALL(Datesonly[Date]),Datesonly[Date] <= Max(Datesonly[Date])))
But the return is the same.. "47753152401"
i'm using graphical filters, and other things to get a minimal view, because there are only 5 weekly reports and the sql database got more than 150.000 rows.
and this is the relation that i made with a only a table full of "dates" in order to invoke the function in a better way, but the result is the same..
Try something along these lines:
IncrmentalValue =
VAR CurrDate = MAX(Datesonly[Date])
VAR PrevDate = CALCULATE(LASTDATE(Datesonly[Date]), Datesonly[Date] < CurrDate)
RETURN SUM(vnxcritical[Used Space GB]) -
CALCULATE(SUM(vnxcritical[Used Space GB]), Datesonly[Date] = PrevDate)
First, calculate the current date and then find the previous date by taking the last date that occurred before it. Then take the difference between the current value and the previous value.
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/
I am plotting a sunburst donut and I cannot figure out why the total is incorrect.
library(sunburstR)
reports <- data.frame(
sequence = c("SVP-VP-Dir-end","SVP-VP-Dir-end","SVP-VP-Dir-end","SVP-VP-Dir-end","SVP-No VP-Dir-end","SVP-No VP-Dir-end","SVP-No VP-Dir-end"),
freq = as.numeric(c("167","60","51","32","5","1","1")))
sunburst(reports, count = TRUE)
It is supposed to be 100% 317 of 317 . Anyone know how to fix this? There is not much documentation on this great package.
Also, I would like it to have a default value in the center of donut.
If there is another way to create an interactive donut using R, please let me know.
Thanks you in advance.
It looks like the default function generating the message in the center of the donut rounds the total value to the nearest ten.
But you can customize this function using the explanation argument of sunburst. Oddly, the customized function (in javascript) must be provided as a string.
Try the following function:
custom.message = "function (d) {
root = d;
while (root.parent) {
root = root.parent
}
p = (100*d.value/root.value).toPrecision(3);
msg = p+' %<br/>'+d.value+' of '+root.value;
return msg;
}"
Now:
sunburst(reports, explanation = custom.message )
will generate the donut displaying exact total values. The count argument is no longer needed, as it is used by the default explanation function.
The value returned by custom.message is html code. As you can see, I've just inserted a line break (<br/>). You can modify the msg return value to further customize the look and feel.
So i have a bar graph in crystal reports. On this graph i have a data label attached to each of the graphs that displays the value of the graph in seconds, which appears like so:
What i would like to do is format this data-label into a time formatting. So for each bar in the graph it would have the data-label appear in the following format:
HH:MM:SS.
i am able to get the time formatting to appear using the following formula:
local NumberVar Sec;
local NumberVar ss;
local NumberVar mm;
local NumberVar hh;
local StringVar SSS;
local StringVar MMM;
Sec := Sum ({GetAlarmSummaryDataSet2Response/GetAlarmSummaryDataSet2Result/Items/AlarmSummaryItem2.StopTime}, {GetAlarmSummaryDataSet2Response/GetAlarmSummaryDataSet2Result/Items/AlarmSummaryItem2.Section}) ;
hh := Int (Sec/3600);
mm :=Int ((Sec/60)- (60* Int(Sec/3600 )));
If mm<10 then MMM := "0" & ToText (mm,0);
If mm>9 Then MMM := ToText(mm,0) ;
ss :=Sec-(3600 * hh ) - (60 * mm ) ;
If ss<10 then SSS := "0" & ToText (ss,0);
If ss>9 Then SSS := ToText(ss,0) ;
ToText ( hh,0) & ":" & MMM & ":" & SSS
But what i am unsure of is how to implement this formula onto a data label.
Any help or suggestions are greatly appreciated.
Thank you
You can choose to display the group name, and you can display and format the summarized value calculated by the chart, but you can't provide a custom formula. It just isn't possible using the chart library in CR XI.
My eventual workaround for this problem:
Modify the value formula to eliminate the aggregate function. (This is necessary because Crystal won't allow an aggregate function in a group name field -- see #2.)
For the group name, specify a formula with the text you want to display in the riser. Include both the label and the formatted value, separated by Chr(13) & Chr(10) to place them on separate lines.
Configure the riser to display the label, not the value.
To apply this to your problem you'd need to make these changes:
Eliminate the aggregate function. Of course I don't know if this will be possible using your setup. Perhaps if you're using a DBMS you could use a SQL command or a stored procedure to calculate the sum before the data reaches Crystal.
Print the label and value together, either on the riser or the X-axis.
If that's not good enough for your application, you might consider CRChart, a commercial replacement which tries to address the sometimes-crippling limitations of Crystal's chart library. (I thought it was too pricey.) I think the #APPEND_DATATEXT macro would let you place a custom value on a riser, but you'd still need to move the summary to the server.
I have a chart with a DateTime axis as my horizontal and a Linear Axis for my vertical inside a Adobe Flex Line Chart. I want to use a Cartesian Data Canvas as a background element and draw custom set of background graphics mostly rectangles. When I have more than a single data point, the graphics work perfectly since they are supposed to span the width of the entire chart.
When I have only a single data point, however, I can't seem to get the rectangles to draw. Since I want my rectangles to span the entire width of the chart, I was thinking that I could get the x-coordinates from my axis, but this isn't working.
var canvasWidth:Number = chtCanvas.width;
var canvasHeight:Number = chtCanvas.height;
var minPt:Array;
var maxPt:Array;
var minPtDate:Date;
var maxPtDate:Date;
var minPtComplete:Point;
var maxPtComplete:Point;
// This works fine when there is more than 1 data point
minPt = chtCanvas.localToData(new Point(0, 0));
maxPt = chtCanvas.localToData(new Point(canvasWidth,canvasHeight));
//This does return a date object, but wont draw below
minPtDate = axisDate.minimum;
maxPtDate = axisDate.maximum;
//This returns NaN for the x
minPtComplete = chtCanvas.dataToLocal(minPtDate, axisSalary.minimum);
maxPtComplete = chtCanvas.dataToLocal(maxPtDate, axisSalary.maximum);
// Also tried this. Also returns NaN for the x value
//minPtComplete = chtCanvas.dataToLocal(axisDate.minimum, axisSalary.minumum);
//maxPtComplete = chtCanvas.dataToLocal(axisDate.maximum, axisSalary.maximum);
My actual drawing method is as follows:
// Tried this, works with points >2, does not draw with single data point
chtCanvas.drawRect(minPt[0], detail[i].MaxValue, maxPt[0], detail[i].MinValue);
//tried this, no effect with single point
//chtCanvas.drawRect(minPtDate, detail[i].MaxValue, maxPtDate, detail[i].MinValue);
// Tried this, no effect with single point
//chtCanvas.drawRect(minPtDate, minPt[1], maxPtDate, detail[i].MinValue);
// Tried this also
//chtCanvas.drawRect(minPtComplete.x, detail[i].MaxValue, maxPtComplete.x, detail[i].MinValue);
In this example, detail is an array collection of salary values and Im using the data value in the array to determine the vertical bounds of my rectangles.
I need to draw the rectangles the entire width of the chart (even when there is only a single data point). Thanks
Thanks to Heikki for his help. The following code works to use the axis values to draw on your Cartesian Data Canvas:
chtCanvas.drawRect(axisDate.minimum as Date, axisSalary.maximum, axisDate.maximum as Date, axisSalary.minimum);
Casting the values as Date really helped. The rest of the code used above is unecessary.
One thing to note, I was using a DateFormatter to format the date values from my data. What I didn't consider was that when using a DateTimeAxis, Flex will automatically add in extra dates to display on the axis. In my case, I was using a custom parse function to create MY points, but wasnt considering the points Flex was creating and also passing to my parse function (Therefore, they were not getting parsed correctly). Once I corrected this, the values laid out correctly in the case of multiple data points. I'm still having a bit of an issue with single data points and them not filling the chart entirely, but they are now drawing.
UPDATE:
Although there are signs of life, the minimum and maximum are still not drawing the entire width of the chart in some cases depending on the dataUnits and labelUnits combination.
UPDATE #2: SOLVED
Ok, so the axis does work as minimum/maximum values for the Cartesian Data Canvas but there is something important to remember. For a single point (and probably for multiple points as well, I just couldnt visually see the difference), when using a custom DateTimeAxis parse function such as what was in the Adobe Flex ASDoc tutorials:
private function axisDateParseFunction(item:String):Date
{
var inputDate:String = item;
inputDate = fmtDate.format(inputDate);
var newDate:Date = new Date();
if(inputDate)
{
var a:Array = inputDate.split('/');
newDate.fullYear = a[2];
newDate.month = a[0] - 1;
newDate.date = a[1];
newDate.hours = 0;
newDate.hoursUTC = 0;
newDate.minutes = 0;
newDate.minutesUTC = 0;
newDate.seconds = 0;
newDate.secondsUTC = 0;
newDate.milliseconds = 0;
newDate.millisecondsUTC = 0;
}
return newDate;
}
You MUST remember to set the UTC values as shown above also. Since the DateTimeAxis uses date AND time, when you create new Date objects, their time values also get set to the local system time. Remember to set those values to zero also or you will get points that dont exactly line up with your axis labels.