I draw a graph where there is time on the horizontal axis and price on the vertical axis.
The price can vary from 0.23487 to 0.8746 or from 20.47 to 45.48 or 1.4578 to 1.6859 or from 9000 to 12000 ... you have an idea, any range can be there. Also, the accuracy of numbers may vary (but usually it is 2 decimal places or 4 decimal places).
Now I need to show prices along the vertical axis, but not all of them are just some significant levels. I need to show as many significant levels as possible, but these levels should not be closer to each other than 30 pixels (.
So, if I have a chart with data whose prices range from 1.4567 to 1.6789 and the chart is 500, I can show a maximum of 16 significant levels. Visible price range: 1.6789-1.4567 = 0.2222. 0.2222 / 16 = 0.0138, so I can show the levels 1.4716, 1.4854, etc. But I want to round these levels to some significant number, for example. 1.4600, 1.4700, 1.4800 ... or 1.4580, 1.4590, 1.4600 ... or 1.4580, 1.4585 ... etc. Therefore, I want to always show as many significant levels as possible, depending on how much space I have, but always only show levels for some significant values (I'm not talking about round values, like 20.25), which are 1, 2 , 2,5, 5 and 10 or their factors (10, 20, 25 ... or 100, 200, 250 ...) or their division (0,1, 0,2, 0,25 ... or 0 , 0001, 0.0002, 0.00025 ...)
I actually got this job, but I don’t like my algorithm at all, it is too long and not elegant. Hope someone can suggest a more elegant and general way. I am looking for an algorithm that I can optionally implement. Below is my current alotism in objective-c. Thanks.
-(float) getPriceLineDenominator { NSArray *possVal = [NSArray arrayWithObjects: [NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:2.0], [NSNumber numberWithFloat:2.5], [NSNumber numberWithFloat:5.0], [NSNumber numberWithFloat:10.0], [NSNumber numberWithFloat:20.0], [NSNumber numberWithFloat:25.0], [NSNumber numberWithFloat:50.0], [NSNumber numberWithFloat:100.0], nil]; float diff = highestPrice-lowestPrice;//range of shown values double multiplier = 1; if(diff<10) { while (diff<10) { multiplier/=10; diff = diff*10; } } else { while (diff>100) { multiplier*=10; diff = diff/10; } } float result = 0; for(NSNumber *n in possVal) { float f = [n floatValue]*multiplier; float x = [self priceY:highestPrice]; float y = [self priceY:highestPrice-f]; if((yx)>=30)//30 is minimum distance between price levels shown { result = f; break; } } return result; }