How to round off x-ticklabels to the nearest 50 - charts

I need to round off the X-ticklabels in an excel chart to the nearest 50. The charts are created in VBA, the data series is in a worksheet so I would be happy to use a solution in either. I have written the following function that rounds to the nearest 50:
Function RoundTo50(number As Double) As Double
RoundTo50 = WorksheetFunction.Round(number * 2, -2) / 2
End Function
I have applied it to the min and max x limits of the chart and it works for them, but I can't work out how to apply this to all the ticklabels in between. I thought of applying it to all the data before plotting but that would alter the plot which I don't want to do. I would prefer for the ticklabels to be slightly misaligned due the rounding.
Can you do this with a formatting string? Or any other way?
Thanks

So the answer is as follows (thanks to Sam Ward for the comment that pushed me in the right direction):
Use my RoundTo50() function to round of the min and max limits to the nearest 50. Calculate what the interval should be for a reasonable amount of grid lines, in my case 12. Round this interval to the nearest 50.
Function RoundTo50(number As Double) As Double
RoundTo50 = WorksheetFunction.Round(number * 2, -2) / 2
End Function
and
With Sheets("Report").ChartObjects.Add(...)
.Chart.Axes(xlCategory).MinimumScale = RoundTo50(Sheets(sheetName).Range("M4"))
.Chart.Axes(xlCategory).MaximumScale = RoundTo50(Sheets(sheetName).Range("M124"))
.Chart.Axes(xlCategory).MajorUnit = RoundTo50((.Chart.Axes(xlCategory).MaximumScale - .Chart.Axes(xlCategory).MinimumScale) / 12)
.Chart.Axes(xlCategory).MinorUnit = .Chart.Axes(xlCategory).MajorUnit / 3
I would still be very much interested in being able to do this with a formatting string though as I have a secondary axis in percent and the grid lines from rounding to 50 are slightly offset with the tick marks of the secondary axis. With a formatting string they would be perfectly aligned (because they would be slightly in the wrong place but I would prefer that).

Related

Adding up doubles result in NaN while trying to calculate distance between two positions?

I'm working on a program in which i want to store the distance the user walked since pressing a button. I retrieve the distance via geolocator package and display it on screen which works just fine.
I know there are some distanceBetween-Function for locations, but as far as i noticed, they are just calculating the distance between 2 points and not the actual distance the user walked (For example, if the user starts at one point X, walks over to Point Y and back to X would end in comparing start-and endpoint (X to X), which results in distance: 0, but i want the distance X -> Y -> X.
I added following function that calculated the distance based on longitude/latitude.
double distance(Position start, Position current){
return double.parse((acos(sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude))*6371).toStringAsFixed(2));
}
I call it every frame and store the distance between the current and last gps position.
Works slowly but fine, except one Problem:
Somewhen, the double suddenly turns into "NaN", and i can't figure out why.
It's completely random when this occurs - At the beginning, it was always around 0.6, but it also occurred around 4.5 and 0.2, so i think the problem may be somewhere else.
Can anybody help?
Or does anybody knows a built-in-function that can solve the same problem?
I tried parsing the double to only have 2 decimal spaces (Didn't round it before) because i thought the number might just got too many decimal spaces to be displayed, but error still occured.
I have a second task that is happening at the same time each time stamp, so i thought it was hindering retrieving the GPS, so i tried disabling it, but it didn't change anything.
It's possible that you are getting numerical stability issues with the spherical law of cosines since you're calculating the distance on every frame? It is known that the formula has conditioning issues for very small distances (less than one meter).
Note that the domain for
arccosine(x) is given by -1 <= x <= 1. If in your case you were to supply a value greater than 1 (or smaller than -1) you would get a NaN result.
If you are still debugging this you can add a simple print statement:
double distance(Position start, Position current){
double x = sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude);
if (x > 1 || x < -1) {
print("error");
}
return ((acos(sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude))*6371));
}
If this is indeed the case, then you have a few options, use the Haversine formula because it is better conditioned for small distances, or simply set x to 1 if it's above 1. This anyway just means that the distance is zero.
For more information (and the Haversine formula) see also: Great circle distance
I really didn't think about the arccosines domain...
So i updated my code with your proposition to:
double distance(Position start, Position current) {
double x = sin(start.latitude) * sin(current.latitude) + cos(start.latitude) * cos(current.latitude) * cos(current.longitude - start.longitude);
if (x > 1 || x < -1) {
if (kDebugMode) {
print("error");
}
return 0;
}
return double.parse((acos(x) * 6371).toStringAsFixed(2));
}
It works fine, thank you for your help!

Charting OHLC candle with SMA 200 using mplfinance plot function

I'm using mplfinance plot function to draw OHLC candlestick chart of a symbol. OHLC data is of 2 min timeframe. Also, I'm plotting sma 20 period and sma 200 period on the same chart. Because of sma200, the number of candles which are displayed on chart is quite huge (almost two days of 2min candle)
Since moving average is calculated internally by plot function so I've to pass the two days of 2 min candle to plot function so that I could get some data points of sma200. Candlestick chart is saved as png file. Now because of around 300 candles displayed on chart (sma20 and sma200 line also displayed), candles are not very clearly displayed.
Is there a way to restrict number of candles which get displayed on chart. If I slice my dataframe to lets say 30 candle, then sma200 will not be calculated in that case due to insufficient number of candles. What I need is sma200 with complete dataset but only fixed number of candle or for a fixed duration chart get displayed like last one hour candle data only.
mpf.plot(df, type='candle', style='charles',
title=title,
ylabel='Price',
ylabel_lower='Shares \nTraded',
mav=(20,200),
savefig=file)
I would suggest that you calculate your own moving average, and plot it using mpf.make_addplot(). This will allow you to calculate a moving average based on one-minute or two-minute candles, while plotting five-minute or ten-minute candles. For example:
# calculate mav values
mav20 = twominute_df['Close'].rolling( 20).mean()
mav200 = twominute_df['Close'].rolling(200).mean()
# resample:
resample_ohlcmap = {'Open' :'first',
'High' :'max',
'Low' :'min',
'Close' :'last',
'Volume':'sum'
}
tenminute_df = twominute_df.resample('10T').agg(resample_ohlcmap)
# plot ten-minute candles with two-minute mavs:
apmavs = [ mpf.make_addplot(mav20),
mpf.make_addplot(mav200) ]
mpf.plot(tenminute_df, type='candle', style='charles',
title=title, ylabel='Price', ylabel_lower='Shares \nTraded',
addplot=apmavs, savefig=file)
References:
resampling
moving average calculation
Thanks Daniel for your help. I'm now able to plot a chart for 60 candles with sma 20 and 200.
Well I don't need resampling as my chart timeframe and moving average time frame both are same.
Please find my code snippet.
# get list of close prices from symbol_docs. symbol_docs contain 2 min OHLC.
close_list = list(map(lambda a: a['close'], symbol_docs))
# sma20 and 200 calculated using ta-lib
sma20 = sma(close_list, 20)
sma200 = sma(close_list, 200)
# call to plot_chart function
plot_chart('TCS', symbol_docs, sma20, sma200)
def plot_chart(symbol, docs, sma20, sma200):
df = pd.DataFrame(docs)
df = df.set_index(['time'])
df.rename(columns={'open': 'Open', 'close': 'Close', 'high': 'High', 'low': 'Low'},
inplace=True)
title = symbol.upper() + ' - 2min'
file = saved_chart_image_abs_path + symbol + '.png'
df['sma20'] = sma20
df['sma200'] = sma200
df_sliced = df[-60:]
apmavs = [mpf.make_addplot(df_sliced['sma20']), mpf.make_addplot(df_sliced['sma200'])]
mpf.plot(df_sliced, type='candle', style='charles',
title=title,
ylabel='Price',
ylabel_lower='Shares \nTraded',
addplot=apmavs,
savefig=file)
telegram_message_sender.send_document(file)
os.remove(file)
Below chart is sent as a document on my telegram group :)

How to round up and down double to the nearest interval in dart/flutter

I'm trying to round down/up for example i want to round down 134.78 with nearest 0.5 the output should be 134.5 and if i round up the output should be 135.0 I tried ((134.78 / 0.5).floorToDouble() * 0.5) but the result is 134.0 not 134.5
Multiply your number by two before any calculations.
Use the desired round feature. (Floor or Ceiling).
Divide the result by two again:
double a = 134.78;
print((2*a).floorToDouble()/2); // prints 134.5
print((2*a).ceilToDouble()/2);// prints 135
Which is the desired result.
You can read more here.

Loss of precision when dividing doubles in swift

I try to find the steps between a min and a max value with a given step-size, using swift 2.1.
So we have a min and a max value, both of type Double. The step-size is a Double too. If min is 0.0 and max 0.5 with steps of 0.1, the result is 6, obviously.
But if I start with -0.1 as the minimum value, the result is 6 too. But should be 7, agree?
Here is my Playground example:
let min:Double = -0.1
let max:Double = 0.5
let step:Double = 0.1
var steps: Int {
return Int((max - min) / step) + 1
}
print("steps: \(steps)") // returns "steps: 6", but should be 7
The result is 6.99999999 if we use a Double for the steps variable. But this loss of precision only occurs when our min value is negative.
Do you know a workaround? I just don't want to round() each time I calculate with Doubles.
When you use Int() it forces truncation of your number, which always rounds towards zero. So, 6.9999 becomes 6 rather than 7, because it's closer to zero. If you use round() first it should help:
var steps: Int {
return Int(round((max - min) / step) + 1.0)
}
That's always not a good idea to calculate integral steps based on floating point ranges, you'll always encounter issues, and you won't be able to do much.
Instead I recommend to build your logic on integral steps, and calculate double values based on integral values (not vice versa as you do). I.e. you don't calculate integral step based on range, but you set your integral number of steps and calculate your double step.

Find area of circle on a grid using euclidean distance?

I would like to have a function where I can input a radius value and have said function spit out the area for that size circle. The catch is I want it to do so for integer based coordinates only.
I was told elsewhere to look at Gauss's circle problem, which looks to be exactly what I'm interested in, but I don't really understand the math behind it (assuming it is actually accurate in calculating what I'm wanting).
As a side note, I currently use a modified circle drawing algorithm which does indeed produce the results I desire, but it just seems so incredibly inefficient (both the algorithm and the way in which I'm using it to get the area).
So, possible answers for this to me would be actual code or pseudocode for such a function if such a thing exists or something like a thorough explanation of Gauss's circle problem and why it is/isn't what I'm looking for.
The results I would hope the function would produce:
Input: Output
0: 1
1: 5
2: 13
3: 29
4: 49
5: 81
6: 113
7: 149
8: 197
9: 253
I too had to solve this problem recently and my initial approach was that of Numeron's - iterate on x axis from the center outwards and count the points within the upper right quarter, then quadruple them.
I then improved the algorithm around 3.4 times.
What I do now is just calculating how many points there are within an inscribed square inside that circle, and what's between that square and the edge of the circle (actually in the opposite order).
This way I actually count one-eighth of the points between the edge of the circle, the x axis and the right edge of the square.
Here's the code:
public static int gaussCircleProblem(int radius) {
int allPoints=0; //holds the sum of points
double y=0; //will hold the precise y coordinate of a point on the circle edge for a given x coordinate.
long inscribedSquare=(long) Math.sqrt(radius*radius/2); //the length of the side of an inscribed square in the upper right quarter of the circle
int x=(int)inscribedSquare; //will hold x coordinate - starts on the edge of the inscribed square
while(x<=radius){
allPoints+=(long) y; //returns floor of y, which is initially 0
x++; //because we need to start behind the inscribed square and move outwards from there
y=Math.sqrt(radius*radius-x*x); // Pythagorean equation - returns how many points there are vertically between the X axis and the edge of the circle for given x
}
allPoints*=8; //because we were counting points in the right half of the upper right corner of that circle, so we had just one-eightth
allPoints+=(4*inscribedSquare*inscribedSquare); //how many points there are in the inscribed square
allPoints+=(4*radius+1); //the loop and the inscribed square calculations did not touch the points on the axis and in the center
return allPoints;
}
Here's a picture to illustrate that:
Round down the length of the side of an inscribed square (pink) in the upper right quarter of the circle.
Go to next x coordinate behind the inscribed square and start counting orange points until you reach the edge.
Multiply the orange points by eight. This will give you the yellow
ones.
Square the pink points. This will give you the dark-blue ones. Then
multiply by four, this will get you the green ones.
Add the points on the axis and the one in the center. This gives you
the light-blue ones and the red one.
This is an old question but I was recently working on the same thing. What you are trying to do is as you said, Gauss's circle problem, which is sort of described here
While I too have difficulty understaning the serious maths behind it all, what it more or less pans out to when not using wierd alien symbols is this:
1 + 4 * sum(i=0, r^2/4, r^2/(4*i+1) - r^2/(4*i+3))
which in java at least is:
int sum = 0;
for(int i = 0; i <= (radius*radius)/4; i++)
sum += (radius*radius)/(4*i+1) - (radius*radius)/(4*i+3);
sum = sum * 4 + 1;
I have no idea why or how this works and to be honest Im a bit bummed I have to use a loop to get this out rather than a single line, as it means the performance is O(r^2/4) rather than O(1).
Since the math wizards can't seem to do better than a loop, I decided to see whether I could get it down to O(r + 1) performance, which I did. So don't use the above, use the below. O(r^2/4) is terrible and will be slower even despite mine using square roots.
int sum = 0;
for(int x = 0; x <= radius; x++)
sum += Math.sqrt(radius * radius - x * x);
sum = sum * 4 + 1;
What this code does is loop from centre out to the edge along an orthogonal line, and at each point adding the distance from line to edge in a perpendicualr direction. At the end it will have the number of points in a quater, so it quadruples the result and adds one because there is also central point. I feel like the wolfram equation does something similar, since it also multiplies by 4 and adds one, but IDK why it loops r^2/4.
Honestly these aren't great solution, but it seems to be the best there is. If you are calling a function which does this regularly then as new radii come up save the results in a look-up table rather than doing a full calc each time.
Its not a part of your question, but it may be relevant to someone maybe so I'll add it in anyway. I was personally working on finding all the points within a circle with cells defined by:
(centreX - cellX)^2 + (centreY - cellY)^2 <= radius^2 + radius
Which puts the whole thing out of whack because the extra +radius makes this not exactly the pythagorean theorem. That extra bit makes the circles look a whole lot more visually appealing on a grid though, as they don't have those little pimples on the orthogonal edges. It turns out that, yes my shape is still a circle, but its using sqrt(r^2+r) as radius instead of r, which apparently works but dont ask me how. Anyway that means that for me, my code is slightly different and looks more like this:
int sum = 0;
int compactR = ((radius * radius) + radius) //Small performance boost I suppose
for(int j = 0; j <= compactR / 4; j++)
sum += compactR / (4 * j + 1) - compactR / (4 * j + 3);
sum = sum * 4 + 1;