I have a data set in an array ranging from 0.00164737 to 0.0021966
What I am trying to do is get the shape fixed by logarithmic scale, then to normalize it ready for drawing on the canvas. Say normalized to 0,100 or -100,0,100 so I can work in pixels
To simply normalize (without doing a log function) between 0-100 this works lovely in a for loop:
normalized[i] = ( ( close[i] - min ) / dif ) * 100;
dif is the close array's max minus it's min toFixed(7)
I am no mathematician but I think I am 'sort of close' with the log part, though I only see a visual difference when I apply a log function during normalization. This messes up the normalization obviously and It also produces Infinity or -Infinity and very unnecessarily large numbers
Notice that the chart is now no longer manageable in pixels as it is not sitting on the canvas properly, so to see what I have done I add 150 to all the y points to bring it into view
So When I do this I am disrupting/changeing things on the same line by applying a logarithmic function (I know this part is wrong)
function logWithBase(n,b){return Math.log(n)/Math.log(b);}
changing the line like so:
normalized[i] = logWithBase( ( close[i] - min ) / dif , 10 ) * 100;
Here is a small part of the data before and after I attempt to make it logarithmic:
Before:
0: "0.00168927"
1: "0.00168742"
2: "0.0016818"
3: "0.00168124"
4: "0.00168067"
5: "0.0016805"
6: "0.00168657"
7: "0.00168362"
8: "0.00166886"
9: "0.00165052" // < why does 0.00165 cause -Infinity
10: "0.0016647"
11: "0.00166251"
12: "0.00166664"
13: "0.00167196"
14: "0.00167084"
15: "0.00167667"
Same set after:
0: 38.93017025063121
1: 36.805636182304255
2: 29.629674005179268
3: 28.845120702345767
4: 28.03173121401521
5: 27.786162417624155
6: 35.79352647194307
7: 32.08579894397015
8: 6.4429326997987175
9: -Infinity // < WOW!!
10: -4.729377348896662
11: -12.015082123716525
12: 0.8395033133056131
13: 13.225477668471285
14: 10.8953699275865
15: 21.850168886727374
Maybe a related clue here
If I get the difference between min and max / 2 (I'll probably get a bad mark for this) and use it as my base (before I do the simple normalization) I see the chart upside down...
var logclose = [];
var base = ( Math.max.apply(this,close) - Math.min.apply(this,close) ) / 2;
for( var i = close.length - 1; i >= 0; i-- ){
logclose[i] = logWithBase( close[i] , base );
}
close=logclose;
Conclusion; I think the last example says that the base should be somehow related to the arrays number range as it does have an effect.
how do I tame the logarithm to not be ridiculously large numbers then normalize it to fit the canvas area?
Please do not recommend I use a library (I prefer vanilla JavaScript where it can be used, plus, I would very much like to grasp this proccess)
Edit, here is the code:
var close=[data]; // for example data see this question (line: 19) as the full data will not fit here (over 10000 entries)
//###
var max=Math.max.apply(this,close);
var min=Math.min.apply(this,close);
var dif=(max-min).toFixed(7);
var normalclose=[];
var logAttemptClose=[];
function logWithBase(n,b){return Math.log(n)/Math.log(b);}
for(var i=close.length-1;i>=0;i--){
normalclose[i]=((close[i]-min)/dif)*100;
logAttemptClose[i]=logWithBase( ( close[i] - min ) / dif , 10 ) * 100; // <-- here bad code
}
//drawing to canvas
var top=100;
var x=1000-100;
var pen=[];
pen[0]=document.getElementById("chart");
pen[0]=pen[0].getContext("2d");
pen[0].clearRect(0,0,1000,300);
pen[0].beginPath();
pen[0].moveTo(x,normalclose[normalclose.length-1]+top);
for(var i=close.length-1;i>=0;i--){
x=x-(2);
pen[0].lineTo(x,normalclose[i]+top);
}
pen[0].strokeStyle='#000000';
pen[0].stroke();
Got Ya!!
Ok, this is not the best fix but it works! If anyone can do this better please post..
Add this to line 2 of the above code (where the comment '###' is):
var Lmax=Math.max.apply(this,close);
var Lmin=Math.min.apply(this,close);
var Ldif=(Lmax-Lmin);
var Logar=[];
var infinity=[];
for(var i=close.length-1;i>=0;i--){
Logar[i]=Math.log((close[i]-Lmin)/Ldif);
if(Logar[i]===-Infinity){infinity.push(i);}
}
close=Logar;
Now we have the array at logarithmic scale but there is always ALWAYS -Infinity in there somewhere so we remove it. On the next line write...
for(var i=0;i<=infinity.length-1;i++){close.splice(infinity[i],1);
Then we can continue with the code moving on to simple normalization and we have a nice new log chart: