Reputation: 11
NOTE: I have attached a link here to a (semi) working version of my program.
I am programming a stock charting program using the Finnhub and P5.js libraries.
I am encountering a problem debugging the code for generating the Y-axis values based on the total range of values of a stock. When calling a window/global variable (window.yAxisRange), the for loop the variable is called within appears to be running before anything is written to said variable.
Specifically, the console shows that the console.log() code that I wrote to check the value of the yAxisRange variable displays twice (once per each iteration of that particular loop). The first instance shows a returned NaN value. The graph within the browser views gives a good example of the problem, in that there appears to be viable numbers being generated, but a NaN value is overlayed on top of them for some reason.
I am perplexed as to why I am receiving a NaN value, as well as why the loop in which the window.yAxisRange is called is running so early.
My code is below (I apologize for any discrepancies as I have spent some time adjusting it):
import finnhub from 'https://cdn.skypack.dev/finnhub';
// Finance API Function Call Below
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "c5cam0iad3ib55bb0ajg"
const finnhubClient = new finnhub.DefaultApi()
let stockTicker = prompt("Please enter the symbol of the stock to chart:");
var yAxisAutoRange = 0
finnhubClient.stockCandles(
stockTicker, "D", ((Math.trunc(Date.now() / 1000)) - 8640000), Date.now(),
(error, data, response) => {
console.log("The maximum stock value of the timeframe is: " + max(Object.values(data.h)));
console.log("The minimum stock value of the timeframe is: " + min(Object.values(data.l)));
console.log("The values of the stock's highs are: " + (Object.values(data.h)))
console.log("The values of the stock's lows are: " + (Object.values(data.l)))
let yAxisRangeUpper = (max(Object.values(data.h))) + (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRangeLower = (min(Object.values(data.l))) - (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRange = (max(Object.values(data.h)) - min(Object.values(data.l))) / 2
window.yAxisRange = Math.trunc(yAxisRange)
console.log("yAxis Range: " + window.yAxisRange);
console.log("range maximum value : " + yAxisRangeUpper);
console.log("range minimum value : " + yAxisRangeLower);
window.yAxisAutoRange = Math.trunc(yAxisRangeUpper / 23);
console.log("yAxisAutoRange: " + yAxisRange);
let xAxisDayArray = []
let dayArrayLoop = data.t.length
let dayArrayLoop2 = data.t.length
window.xAxisDayArray = []
window.dayArrayLoop = data.t.length
window.dayArrayLoop2 = data.t.length
for (dayArrayLoop = dayArrayLoop; dayArrayLoop > dayArrayLoop2 - 44; dayArrayLoop = dayArrayLoop - 1) {
xAxisDayArray[dayArrayLoop] = JSON.stringify(new Date(data.t[dayArrayLoop - 1] * 1000));
xAxisDayArray[dayArrayLoop] = parseInt(xAxisDayArray[dayArrayLoop].slice(9, 11))
window.xAxisDayArray[dayArrayLoop] = xAxisDayArray[dayArrayLoop]
//console.log("Data point " + dayArrayLoop + "for date " + xAxisDayArray[dayArrayLoop])
}
}
);
var month = 0
// P5 Chart Background Below
globalThis.setup = function() {
createCanvas(1080, 768);
background(220);
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const d = new Date();
window.month = months[d.getMonth()];
console.log(month)
const day = new Date();
day.getDate();
textSize(18)
text(window.month.slice(0, 3), 1030, 755);
}
globalThis.draw = function() {
// rect(yAxisAutoRange, 300, 10, 100);
let i = 20;
for (i = 20; i < 1020; i = i + 25) {
let y = 0;
for (line(1025, 0, 1025, 768), y = 0; y < 730; y = y + 15) {
stroke(140, 25);
line(i, y, (i + 10), y)
};
}
let z = 10;
for (z = 10; z < 730; z = z + 15) {
let x = 25;
for (line(0, 730, 1080, 730), x = 25; x < 1026; x = x + 25) {
line(x, z, x, (z + 10))
}
}
let yAxisLine = 730
let yAxisIndLocate = 710
let yAxisMultiple = 1
let yAxisNum = String(parseInt(window.yAxisAutoRange * yAxisMultiple))
// May need to simplify loop structure so as to cancel recurring drawing functions
for (yAxisLine = 705, yAxisIndLocate = 710, yAxisMultiple = 1; yAxisLine > 14, yAxisIndLocate > 14, yAxisMultiple < 24; yAxisLine = yAxisLine - 30, yAxisIndLocate = yAxisIndLocate - 30, yAxisMultiple = yAxisMultiple + 1) {
console.log("Y Axis Auto Range = " + window.yAxisAutoRange);
stroke(51)
line(1025, yAxisLine, 1040, yAxisLine);
textSize(18);
//console.log("Endless Loop Test " + yAxisNum) //window.yAxisAutoRange not registerring
//console.log("Y Axis Ind = " + window.yAxisRange);
text(window.yAxisRange / 23 * yAxisMultiple, 1045, yAxisIndLocate);
}
let xAxisLine = 1000
let xAxisIndLocate = 0
for (xAxisLine = 1000, window.dayArrayLoop = window.dayArrayLoop; xAxisLine > 24, window.dayArrayLoop > window.dayArrayLoop2 - 41; xAxisLine = xAxisLine - 25, window.dayArrayLoop = window.dayArrayLoop - 1) {
stroke(51)
line(xAxisLine, 730, xAxisLine, 745);
//console.log(xAxisLine);
text(parseInt(window.xAxisDayArray[dayArrayLoop]), xAxisLine - 5, 760)
noLoop()
}
}
Upvotes: 1
Views: 221
Reputation: 20180
First off, here's how you get this code running as a snippet on stack overflow (with added debugging):
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script type="module">
import finnhub from 'https://cdn.skypack.dev/finnhub';
// Finance API Function Call Below
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "c5cam0iad3ib55bb0ajg"
const finnhubClient = new finnhub.DefaultApi()
let stockTicker = prompt("Please enter the symbol of the stock to chart:");
var yAxisAutoRange = 0;
console.log('module scope yAxisAutoRange: ' + yAxisAutoRange);
console.log('window.yAxisAutoRange: ' + window.yAxisAutoRange);
console.log("Requesting data for " + stockTicker);
finnhubClient.stockCandles(
stockTicker, "D", ((Math.trunc(Date.now() / 1000)) - 8640000), Date.now(),
(error, data, response) => {
console.log("The maximum stock value of the timeframe is: " + max(Object.values(data.h)));
console.log("The minimum stock value of the timeframe is: " + min(Object.values(data.l)));
console.log("The values of the stock's highs are: " + (Object.values(data.h)))
console.log("The values of the stock's lows are: " + (Object.values(data.l)))
let yAxisRangeUpper = (max(Object.values(data.h))) + (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRangeLower = (min(Object.values(data.l))) - (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRange = (max(Object.values(data.h)) - min(Object.values(data.l))) / 2
window.yAxisRange = Math.trunc(yAxisRange)
console.log("yAxis Range: " + window.yAxisRange);
console.log("range maximum value : " + yAxisRangeUpper);
console.log("range minimum value : " + yAxisRangeLower);
window.yAxisAutoRange = Math.trunc(yAxisRangeUpper / 23);
console.log("yAxisAutoRange: " + yAxisRange);
let xAxisDayArray = []
let dayArrayLoop = data.t.length
let dayArrayLoop2 = data.t.length
window.xAxisDayArray = []
window.dayArrayLoop = data.t.length
window.dayArrayLoop2 = data.t.length
for (dayArrayLoop = dayArrayLoop; dayArrayLoop > dayArrayLoop2 - 44; dayArrayLoop = dayArrayLoop - 1) {
xAxisDayArray[dayArrayLoop] = JSON.stringify(new Date(data.t[dayArrayLoop - 1] * 1000));
xAxisDayArray[dayArrayLoop] = parseInt(xAxisDayArray[dayArrayLoop].slice(9, 11))
window.xAxisDayArray[dayArrayLoop] = xAxisDayArray[dayArrayLoop]
//console.log("Data point " + dayArrayLoop + "for date " + xAxisDayArray[dayArrayLoop])
}
}
);
var month = 0
console.log("Declaring p5.js sketch");
// P5 Chart Background Below
globalThis.setup = function() {
console.log("p5.js sketch setup");
createCanvas(1080, 768);
background(220);
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const d = new Date();
window.month = months[d.getMonth()];
console.log(month)
const day = new Date();
day.getDate();
textSize(18)
text(window.month.slice(0, 3), 1030, 755);
// Slow down the framerate so we don't spam the logs during debugging
frameRate(5);
}
globalThis.draw = function() {
console.log('p5.js draw');
// rect(yAxisAutoRange, 300, 10, 100);
let i = 20;
for (i = 20; i < 1020; i = i + 25) {
let y = 0;
for (line(1025, 0, 1025, 768), y = 0; y < 730; y = y + 15) {
stroke(140, 25);
line(i, y, (i + 10), y)
};
}
let z = 10;
for (z = 10; z < 730; z = z + 15) {
let x = 25;
for (line(0, 730, 1080, 730), x = 25; x < 1026; x = x + 25) {
line(x, z, x, (z + 10))
}
}
let yAxisLine = 730
let yAxisIndLocate = 710
let yAxisMultiple = 1
let yAxisNum = String(parseInt(window.yAxisAutoRange * yAxisMultiple))
console.log("Y Axis Auto Range = " + window.yAxisAutoRange);
// May need to simplify loop structure so as to cancel recurring drawing functions
for (yAxisLine = 705, yAxisIndLocate = 710, yAxisMultiple = 1; yAxisLine > 14, yAxisIndLocate > 14, yAxisMultiple < 24; yAxisLine = yAxisLine - 30, yAxisIndLocate = yAxisIndLocate - 30, yAxisMultiple = yAxisMultiple + 1) {
stroke(51)
line(1025, yAxisLine, 1040, yAxisLine);
textSize(18);
//console.log("Endless Loop Test " + yAxisNum) //window.yAxisAutoRange not registerring
//console.log("Y Axis Ind = " + window.yAxisRange);
text(window.yAxisRange / 23 * yAxisMultiple, 1045, yAxisIndLocate);
}
let xAxisLine = 1000
let xAxisIndLocate = 0
for (xAxisLine = 1000, window.dayArrayLoop = window.dayArrayLoop; xAxisLine > 24, window.dayArrayLoop > window.dayArrayLoop2 - 41; xAxisLine = xAxisLine - 25, window.dayArrayLoop = window.dayArrayLoop - 1) {
stroke(51)
line(xAxisLine, 730, xAxisLine, 745);
//console.log(xAxisLine);
text(parseInt(window.xAxisDayArray[dayArrayLoop]), xAxisLine - 5, 760)
noLoop()
}
}
</script>
Because you are using a top level import, and Stack Snippets don't support that, you have to move all of your JavaScript into the HTML (which is kind of a bummer and StackOverflow should fix this).
That being said, the fundamental issue here is that you are making an asynchronous request for data, and then immediately initializing a p5.js sketch that depends on that data (or at least on a value calculated from it). Consider the following console log output:
Requesting data for tsla
Declaring p5.js sketch
p5.js sketch setup
You just changed the value of "month", which was a p5 function. This could cause problems later if you're not careful.
0
p5.js draw
Y Axis Auto Range = undefined
... repeatedly
p5.js draw
Y Axis Auto Range = undefined
The maximum stock value of the timeframe is: 1243.49
The minimum stock value of the timeframe is: 813.35
The values of the stock's highs are: 820.25,843.21,...
The values of the stock's lows are: 813.35,822.35,...
yAxis Range: 215
range maximum value : 1673.63
range minimum value : 383.21
yAxisAutoRange: 215.07
p5.js draw
Y Axis Auto Range = 72
Hopefully it is self evident from this that it is only natural that yAxisAutoRange
is initially undefined
and thus window.yAxisRange / 23 * yAxisMultiple
is NaN
: because the code that computes it hasn't run yet!
Also, be careful using the ,
operator in the condition expression for for loops! false, true
is true
and true, false
is false
. I'm not sure that is what you meant to do (perhaps you should be using either ||
for logical or, or &&
for logical and.
Upvotes: 1