问题描述
您在下方看到的线代表平均 9 分钟。
该线在图表末尾反转,然后反转回到自身,然后停在图表中间。我的问题是该行不应该在最后自己折回,我不知道为什么会这样。
我可以看到来自 2021-5-13-02-00 的数据导致了反转,但是,来自 2021-5-13-02-00 的数据不存在于生成的 CSV 文件数据的末尾。
我需要找出我没有输入的这些数据的来源。
任何解决此问题的帮助都会很棒,谢谢!
margin = {top: 0,bottom: 20,left: 40,right: 20}
function apply_attrs(selection,attrs_func,xScale,yScale) {
const s = attrs_func(selection,yScale)
return s
}
function path_9_attr_func(selection,yScale) {
selection
.attr("fill","none")
.attr("stroke","#00ff00")
.attr("d",linefunc(xScale,yScale,9))
return selection
}
function max_in_obj(data,property_name) {
const high = data.reduce((acc,cur,ind) => {
if (cur[property_name] > acc) {
acc = cur[property_name]
}
return acc
},data[0][property_name])
return high
}
function min_in_obj(data,property_name) {
const low = data.reduce((acc,ind) => {
if (cur[property_name] < acc) {
acc = cur[property_name]
}
return acc
},data[0][property_name])
return low
}
const linefunc = (xScale,n) => {
return d3.line()
.x((d,i,data) => {
if (isNaN(d.date)) {
return 0
}
let retval = xScale(d.date)
if (d.date.getMinutes() === 30) {
console.log("Here is 30",d,i)
}
return retval
})
.y((d,data) => {
let sliced;
sliced = data.slice(i-(n-1),i+1);
const val = (min_in_obj(sliced,"low") + max_in_obj(sliced,"high")) / 2
return yScale(val)
}).defined((d,data) => i >= n-1)
}
const f = async () => {
let num = 0
let res = await fetch("https://gist.githubusercontent.com/KiYugadgeter/a8527ff1d9aa12f68b9d48d6fc09496a/raw/4bd019b8c6d6e2be2ecfd7180a64a6356fc34f11/stack_overflow_why_invert.csv")
let d = await res.text()
let min_value = 999999999
let max_value = 0
data = parsed_data = d3.csvParse(d,(dt) => {
const j = dt.date.split("-").map((i) => {
const p = parseInt(i)
return p
})
const date = new Date(j[0],j[1]-1,j[2],j[3],j[4],0)
//num++
console.log(date,dt)
high_value = parseFloat(dt.high)
low_value = parseFloat(dt.low)
open_value = parseFloat(dt.open)
close_value = parseFloat(dt.close)
if (low_value < min_value) {
min_value = low_value
}
if (high_value > max_value) {
max_value = high_value
}
return {
open: open_value,close: close_value,high: high_value,low: low_value,date: date
}
})
return {data: data,min: min_value,max: max_value}
}
f().then((d) => {
let num = 0
let recently_date = d.data[d.data.length-1].date
let minvalue = 99999999999
let maxvalue = 0
recently_date.setMinutes(recently_date.getMinutes() - (recently_date.getMinutes() % 30))
recently_date.setSeconds(0)
recently_date.setMilliseconds(0)
recently_date = new Date(recently_date.getTime() + 30 * 60000)
const limit_date = (recently_date - (60 * 90 * 1000))
let data = d.data.filter((d) => {
num++
if (d.low < minvalue) {
minvalue = d.low
}
if (d.high > maxvalue) {
maxvalue = d.high
}
return true
})
const svg = d3.select("svg")
const xScale = d3.scaleTime().domain(
[
limit_date,recently_date
]
).nice().range([margin.left,600-margin.left-margin.right])
const yScale = d3.scaleLinear().domain([(maxvalue - (maxvalue%1000) + 2000),(minvalue - (minvalue%1000) - 2000)]).range([0,410-margin.top-margin.bottom])
const canvas = svg.append("g").attr("width",600).attr("height",410)
const clip = svg.append("clipPath").attr("id","clip").append("rect").attr("width",600-margin.left-margin.right).attr("height",410-margin.bottom-margin.top).attr("x",margin.left).attr("y",0)
const candles_layer = canvas // Data group
.append("g")
.attr("stroke-linecap","square")
.attr("stroke","black")
.attr("clip-path","url(#clip)")
const path_9min = canvas
.append("path")
const path_9_selection = path_9min
.attr("clip-path","url(#clip)")
.datum(data)
apply_attrs(path_9_selection,path_9_attr_func,yScale)
const xaxis = d3.axisBottom(xScale).ticks().tickFormat(d3.timeFormat("%H:%M"))
const group_x = canvas
.append("g")
.attr("transform","translate(0," + String(410-margin.top - margin.bottom) + ")") // X axis
.call(xaxis).style("font-size","5")
const yaxis = d3.axisLeft(yScale)
const group_y = canvas
.append("g")
.attr("class","axis axis--y")
.attr("transform","translate(" + String(margin.left) + ",0)") // Y axis
.call(yaxis)
.style("font-size","5")
})
<!DOCTYPE html>
<html lang="ja">
<head>
<Meta charset="utf-8">
<script src="https://d3js.org/d3.v6.min.js"></script>
<Meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="index.css">
</head>
<body>
<svg id="svg" viewBox="0 0 600 410">
</svg>
</body>
</html>
解决方法
我清楚地看到您的上一个时间戳可以追溯到过去 (02:28:00 -> 02:00:00)
808: {open: 28935.51,close: 29053.97,high: 29139.7,low: 28875.91,date: Thu May 13 2021 02:28:00}
809: {open: 28996.66,close: 28812.63,high: 29046.49,low: 28760.27,date: Thu May 13 2021 02:00:00}
该代码段演示了从数据中删除最后一项可以解决问题:
margin = {top: 0,bottom: 20,left: 40,right: 20}
function apply_attrs(selection,attrs_func,xScale,yScale) {
const s = attrs_func(selection,yScale)
return s
}
function path_9_attr_func(selection,yScale) {
selection
.attr("fill","none")
.attr("stroke","#00ff00")
.attr("d",d => linefunc(xScale,yScale,9,d))
return selection
}
function max_in_obj(data,property_name) {
const high = data.reduce((acc,cur,ind) => {
if (cur[property_name] > acc) {
acc = cur[property_name]
}
return acc
},data[0][property_name])
return high
}
function min_in_obj(data,property_name) {
const low = data.reduce((acc,ind) => {
if (cur[property_name] < acc) {
acc = cur[property_name]
}
return acc
},data[0][property_name])
return low
}
const linefunc = (xScale,n,d) => {
return d3.line()
.x((d,i,data) => {
if (isNaN(d.date)) {
return 0
}
let retval = xScale(d.date)
if (d.date.getMinutes() === 30) {
console.log("Here is 30",d,i)
}
return retval
})
.y((d,data) => {
let sliced;
sliced = data.slice(i-(n-1),i+1);
const val = (min_in_obj(sliced,"low") + max_in_obj(sliced,"high")) / 2
return yScale(val)
}).defined((d,data) => i >= n-1)(d.slice(0,-1));
}
const f = async () => {
let num = 0
let res = await fetch("https://gist.githubusercontent.com/KiYugadgeter/a8527ff1d9aa12f68b9d48d6fc09496a/raw/4bd019b8c6d6e2be2ecfd7180a64a6356fc34f11/stack_overflow_why_invert.csv")
let d = await res.text()
let min_value = 999999999
let max_value = 0
data = parsed_data = d3.csvParse(d,(dt) => {
const j = dt.date.split("-").map((i) => {
const p = parseInt(i)
return p
})
const date = new Date(j[0],j[1]-1,j[2],j[3],j[4],0)
//num++
console.log(date,dt)
high_value = parseFloat(dt.high)
low_value = parseFloat(dt.low)
open_value = parseFloat(dt.open)
close_value = parseFloat(dt.close)
if (low_value < min_value) {
min_value = low_value
}
if (high_value > max_value) {
max_value = high_value
}
return {
open: open_value,close: close_value,high: high_value,low: low_value,date: date
}
})
return {data: data,min: min_value,max: max_value}
}
f().then((d) => {
let num = 0
let recently_date = d.data[d.data.length-1].date
let minvalue = 99999999999
let maxvalue = 0
recently_date.setMinutes(recently_date.getMinutes() - (recently_date.getMinutes() % 30))
recently_date.setSeconds(0)
recently_date.setMilliseconds(0)
recently_date = new Date(recently_date.getTime() + 30 * 60000)
const limit_date = (recently_date - (60 * 90 * 1000))
let data = d.data.filter((d) => {
num++
if (d.low < minvalue) {
minvalue = d.low
}
if (d.high > maxvalue) {
maxvalue = d.high
}
return true
})
const svg = d3.select("svg")
const xScale = d3.scaleTime().domain(
[
limit_date,recently_date
]
).nice().range([margin.left,600-margin.left-margin.right])
const yScale = d3.scaleLinear().domain([(maxvalue - (maxvalue%1000) + 2000),(minvalue - (minvalue%1000) - 2000)]).range([0,410-margin.top-margin.bottom])
const canvas = svg.append("g").attr("width",600).attr("height",410)
const clip = svg.append("clipPath").attr("id","clip").append("rect").attr("width",600-margin.left-margin.right).attr("height",410-margin.bottom-margin.top).attr("x",margin.left).attr("y",0)
const candles_layer = canvas // Data group
.append("g")
.attr("stroke-linecap","square")
.attr("stroke","black")
.attr("clip-path","url(#clip)")
const path_9min = canvas
.append("path")
const path_9_selection = path_9min
.attr("clip-path","url(#clip)")
.datum(data)
apply_attrs(path_9_selection,path_9_attr_func,yScale)
const xaxis = d3.axisBottom(xScale).ticks().tickFormat(d3.timeFormat("%H:%M"))
const group_x = canvas
.append("g")
.attr("transform","translate(0," + String(410-margin.top - margin.bottom) + ")") // X axis
.call(xaxis).style("font-size","5")
const yaxis = d3.axisLeft(yScale)
const group_y = canvas
.append("g")
.attr("class","axis axis--y")
.attr("transform","translate(" + String(margin.left) + ",0)") // Y axis
.call(yaxis)
.style("font-size","5")
})
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v6.min.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="index.css">
</head>
<body>
<svg id="svg" viewBox="0 0 600 410">
</svg>
</body>
</html>