I am trying to render tradingview chart using tradingview charting library and using bitquery api for datafeed.
Chart is being displayed but there is no data on the chart.
I opened the inspect element and noticed this:
More specifically the part about RangeError: Invalid time value I am assuming that's what's causing the chart to not load any candlestick data?
This is the section of the code in datafeed.js:
// This method is used by the charting library to get historical data for the symbol.
getBars: async(symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, first) =>{
try{
if (resolution==='1D') {
resolution = 1440;
}
const response2 = await axios.post(Bitquery.endpoint, {
query: Bitquery.GET_COIN_BARS,
variables: {
"from": new Date(from).toISOString(),
"to": new Date(to).toISOString(),
"interval": Number(resolution),
"tokenAddress": symbolInfo.ticker
},
mode: 'cors',
headers: {
"Content-Type": "application/json",
"X-API-KEY": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
})
const bars = response2.data.data.ethereum.dexTrades.map(el => ({
time: new Date(el.timeInterval.minute).getTime(), // date string in api response
low: el.low,
high: el.high,
open: Number(el.open),
close: Number(el.close),
volume: el.volume
}))
if (bars.length){
onHistoryCallback(bars, {noData: false});
}else{
onHistoryCallback(bars, {noData: true});
}
} catch(err){
console.log({err})
// onErrorCallback(err)
}
I am fairly new with tradingview charting library and JS, so I need suggestions to fix this.
Related
I am doing a web app using react and nodeJS and I am trying to get my pie chart to only display unique values and add the repeated string values so it looks nice and clean
Right now this is what is showing.
(Pie chart and array on picture) https://i.stack.imgur.com/SvrXk.png This is a dynamic array that am i fetching the info from an api and saving it into a 2d array
This is the code am using to populate the array (Last for loop)
const getTransactions = async (accountId) => {
setIncome(0);
setExpenses(0);
await fetch("http://localhost:4000/api/plaid/transactions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${user.token}`,
},
body: JSON.stringify({
account_id: accountId,
}),
})
.then((response) => response.json())
.then((response) => {
setTransactions(response.transactions);
response.transactions.forEach((transaction) => {
if (transaction.amount > 0) {
setIncome((prevState) => prevState + transaction.amount);
} else {
setExpenses((prevState) => prevState - transaction.amount);
}
});
tempPieData.push(["Names", "Amounts"]);
for (let dataObj of response.transactions) {
tempPieData.push([dataObj.category[0], Math.abs(dataObj.amount)]);
}
console.log(tempPieData);
setPieData(tempPieData);
});
};
This is how am loading the pie chart using react google charts
const options = {
pieHole: 0.4,
is3D: false,
width: 500,
height: 500,
};
{selectedAccount !== null && (
<div className="pieChart">
<Chart chartType="PieChart" data={PieData} options={options} />
</div>
Any help or Ideas on how I can make this only show "Travel" and "Food and Drinks" on the legend and the combination of values of the repeated strings in the array. No hard code please I am looking for dynamic since I cant know what category of transactions the user is going to make.
I am trying get Isochrone contours when the user clicks on a Marker,
The official Mapbox Documentation uses the built in Mapbox JS methods but I can't make it work with Leaflet JS
Here's what I have
function markerOnClick(lon, lat) {
const urlBase = "https://api.mapbox.com/isochrone/v1/mapbox/";
const profile = "cycling"; // Set the default routing profile
const minutes = 10; // Set the default duration
// Create a function that sets up the Isochrone API query then makes an fetch call
async function getIso() {
const query = await fetch(
`${urlBase}${profile}/${lon},${lat}?contours_minutes=${minutes}&polygons=true&access_token=${accessToken}`,
{ method: "GET" }
);
const data = await query.json();
map.getSource("iso").setData(data);
}
// From the official documentation
map.addSource("iso", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [],
},
});
// I have tried to use the Leaflet geoJSON method to add it to the map
L.geoJSON("iso", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [],
},
}).addTo(map);
// Can't find the substitute for this method in Leaflet
map.addLayer(
{
id: "isoLayer",
type: "fill",
// Use "iso" as the data source for this layer
source: "iso",
layout: {},
paint: {
// The fill color for the layer is set to a light purple
"fill-color": "#5a3fc0",
"fill-opacity": 0.3,
},
},
"poi-label"
);
// Make the API call
getIso();
}
I have tried to use the Leaflet method of adding GeoJSON to the map i.e. L.geoJSON but to no avail the mapbox GL JS methods I am trying to replace are
map.addLayer
map.addSource
any advice would be appreciated
L.geoJSON() expects a GeoJSON data structure, not a string. Do read https://leafletjs.com/reference#geojson .
For your particular case you probably want to do something like
const query = await fetch(`${urlBase}${profile}/${lon},${lat}?contours_minutes=${minutes}&polygons=true&access_token=${accessToken}`,{ method: "GET" });
const data = await query.json();
L.geoJson(data).addTo(map);
I am working with audio streams in Node.js. As for now, my code doesn't have utils.promisfy and I have 3 stages of it. So after the 2nd .pipe I am writing file to disk in wav audio format with required params.
Code example below:
import { FileWriter } from 'wav';
const filename = `./${Date.now()}-${userId}.wav`;
const encoder = new OpusEncoder(16000, 1);
receiver
.subscribe(userId, {
end: {
behavior: EndBehaviorType.AfterSilence,
duration: 100,
},
})
// OpusDecodingStream is a custom class, which convert audio, like a gzip stage for file.
.pipe(new OpusDecodingStream({}, encoder))
.pipe(
// Writes wav file to disk, also can be replaces with FileRead, part of wav module
new FileWriter(filename, {
channels: 1,
sampleRate: 16000,
}),
);
The problem is: I need to transfer (not streaming!) resulting audio file in binary format via axios POST method. So I guess, it's a bit wrong to write file on disk instead of writing it in variable, and after stream ends, send it right to required URL. Something (by logic) which I'd like to see:
// other code
const fileStringBinary = await receiver
.subscribe(userId, {
end: {
behavior: EndBehaviorType.AfterSilence,
duration: 100,
},
})
.pipe(new OpusDecodingStream({}, encoder))
.pipe(
return new FileWriter(filename, {
channels: 1,
sampleRate: 16000,
}),
);
await axios.post('https://url.com', {
data: fileStringBinary
});
Unfortunately I am not so good with streams and especially with audio one, so I am looking for a bit help or any useful advice will be welcome for me.
I understand, that I could write my file to directory, find it there, read once again with node:steam createReadStream and then POST it to required URL. This is not what I need. I'd like to skip this useless stages with writing and then reading. I believe that there is a way to transform steam to binary format and write it down to js variable.
That was a bit treaky after all, but I guess I figure it out:
const stream = receiver
.subscribe(userId, {
end: {
behavior: EndBehaviorType.AfterSilence,
duration: 100,
},
})
.pipe(
new opus.OggLogicalBitstream({
opusHead: new opus.OpusHead({
channelCount: 2,
sampleRate: 48000,
}),
pageSizeControl: {
maxPackets: 10,
},
crc: false,
}),
);
const data = [];
stream.on('data', (chunk) => {
data.push(chunk);
});
stream.on('end', async () => {
try {
const response = await axios.post(
`https://url.com${postParams}`,
Buffer.concat(data),
{
headers: {
Authorization: `Api-Key ${token}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
},
);
console.log(response);
} catch (e) {
console.log(e);
}
});
Unfortunately, I haven't found a better solution, then using old-school events model with data and on end. My working case is connected with Discord.js voice recording without file and using stream for voice recognition.
I will be glad if someone will provide a better-syntax solution, and in that case I'll accept this answer as solved.
I am setting up a website displaying chart using tradingview chart library, and managed to setup chart to display from data feed. However once chart is loaded, the chart is not auto updating or refreshing with newer data without reloading webpage. How do I setup the chart to update automatically (eg. interval 1m, 5m etc)? This is the code I used:
function initOnReady() {
var widget = window.tvWidget = new TradingView.widget({
// debug: true, // uncomment this line to see Library errors and warnings in the
fullscreen: true,
symbol: 'AAPL',
interval: '1D',
container_id: "tv_chart_container",
// BEWARE: no trailing slash is expected in feed URL
datafeed: new Datafeeds.UDFCompatibleDatafeed("<data feed url>"),
library_path: "charting_library/",
locale: getParameterByName('lang') || "en",
disabled_features: ["use_localstorage_for_settings"],
enabled_features: ["study_templates"],
charts_storage_url: 'https://saveload.tradingview.com',
charts_storage_url: 'http://{$smarty.server.HTTP_HOST}',
charts_storage_api_version: "1.1",
client_id: 'tradingview.com',
user_id: 'public_user_id',
});
};
Thanks in advance and appreciate for helps.
create file named datafeed like so:
export default {
onReady: (callback) => {
console.log("[onReady]: Method call");
callback({});
},
searchSymbols: (userInput, exchange, symbolType, onResultReadyCallback) => {
console.log("[searchSymbols]: Method call");
},
resolveSymbol: (
symbolName,
onSymbolResolvedCallback,
onResolveErrorCallback
) => {
console.log("[resolveSymbol]: Method call", symbolName);
},
getBars: async (
symbolInfo,
resolution,
from,
to,
onHistoryCallback,
onErrorCallback,
firstDataRequest
) => {
},
subscribeBars: (
symbolInfo,
resolution,
onRealtimeCallback,
subscribeUID,
onResetCacheNeededCallback
) => {
console.log(
"[subscribeBars]: Method call with subscribeUID:",
subscribeUID
);
},
unsubscribeBars: (subscriberUID) => {
console.log(
"[unsubscribeBars]: Method call with subscriberUID:",
subscriberUID
);
},
};
and replace it with datafeeds:
import DATAFEED from './datafeed';
function initOnReady() {
var widget = window.tvWidget = new TradingView.widget({
// debug: true, // uncomment this line to see Library errors and warnings in the
fullscreen: true,
symbol: 'AAPL',
interval: '1D',
container_id: "tv_chart_container",
// BEWARE: no trailing slash is expected in feed URL
datafeed: DATAFEED, // ---> replace here
library_path: "charting_library/",
locale: getParameterByName('lang') || "en",
disabled_features: ["use_localstorage_for_settings"],
enabled_features: ["study_templates"],
charts_storage_url: 'https://saveload.tradingview.com',
charts_storage_url: 'http://{$smarty.server.HTTP_HOST}',
charts_storage_api_version: "1.1",
client_id: 'tradingview.com',
user_id: 'public_user_id',
});
};
Notice : Trading view itself manage most actions base on what it needs.
for example
if you want to drag the candle chart, trading view calculate the view port and find out how many candle it need's to show then call getBars method in datafeeds.js.
for see examples:
https://github.com/tradingview/charting-library-examples
I am calling some data in via an api for an ionic app I'm making. The data is being called asynchronously and I need to assign the data to different variables for use in a chart that gets presented to the user. I'm struggling to assign the data to a variable that I can then access from the function which creates the chart (I'm using chart.js). Initially I've been trying to grab a list of dates from the data for use as the X axis scale, just to get things working.
Been trying quite a few things and failing. I initially thought it was because my variable was block scoped, but now I think its an async issue. Been reading about promises for hours, but although I understand the concept I can't see away to apply it to my current code (presuming the issue is async! I'm a noob on a self teaching mission here).
So this the code which handles pulling in the data from the api
async getData() {
const loading = await this.loadingController.create({
message: 'Loading'
});
await loading.present();
this.api.getData()
.subscribe(res => {
console.log(res);
this.data1 = res[0];
loading.dismiss();
console.log(this.data1);
const datelabel = this.data1.result[1].date;
}, err => {
console.log(err);
loading.dismiss();
});
}
And this is the code which creates the chart
useAnotherOneWithWebpack() {
var ctx = (<any>document.getElementById('canvas-linechart')).getContext('2d');
console.log('GotData', this.datelabel); //just to see what data I've got here if any in the console
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: this.datelabel,
datasets: [{
data: [86,114,106],
label: "Africa",
borderColor: "#3e95cd",
fill: false
}, {
data: [282,350,411],
label: "Asia",
borderColor: "#8e5ea2",
fill: false
}, {
data: [168,170,178],
label: "Europe",
borderColor: "#3cba9f",
fill: false
}
]
},
options: {
title: {
display: true,
text: 'World population per region (in millions)'
}
}
});
}
So I'm calling the datalabel variable against labels, but its displaying as undefined on the axis and in the console. I'm expecting to see three months (which are saved as strings in the variable). Tried all sorts now and its driving me a bit mad. I'm not even sure its an async issue, but from what I've done so far it feels like the issue.
Any help really appreciated!!
Not sure when/where you're calling the useAnotherOneWithWebpack() method but one issue from your code is that you're assigning some values to the local constant datelabel but not to the property from the component:
// The following line just creates a local const available only in that scope
const datelabel = this.data1.result[1].date;
Instead, you should be initializing the component's property:
this.datelabel = this.data1.result[1].date;
Keeping that in mind, please try the following:
async getData() {
const loading = await this.loadingController.create({
message: 'Loading'
});
await loading.present();
this.api.getData().subscribe(
res => {
// This line will be executed when getData finishes with a success response
console.log('Inside of the subscribe - success');
console.log(res);
this.data1 = res[0];
this.datelabel = this.data1.result[1].date;
// Now that the data is ready, you can build the chart
this.useAnotherOneWithWebpack();
loading.dismiss();
},
err => {
// This line will be executed when getData finishes with an error response
console.log('Inside of the subscribe - error');
console.log(err);
loading.dismiss();
});
// This line will be executed without waiting for the getData async method to be finished
console.log('Outside of the subscribe');
}