I am trying to implement a stock chart with swift with two plots: one is the price and the other is a prediction/approximate for the price. I tried to implement this by using two loops of LineMark like below. For testing purpose, I used the same dataset with one's x value shifted up by 1. But I got the following issue where the start and end y values are connected when I add in a second loop of LineMark. How can I fix this?
VStack {
Chart {
ForEach(self.entries, id: \.date) { entry in
LineMark(
x: .value("Date", entry.date),
y: .value("Price", entry.closePrice + 1)
).foregroundStyle(.green)
}
ForEach(self.entries, id: \.date) { entry in
LineMark(
x: .value("Date", entry.date),
y: .value("Price", entry.closePrice)
)
.foregroundStyle(.blue)
let curGradient = LinearGradient(
gradient: Gradient (
colors: [
.green.opacity(0.5),
.green.opacity(0.2),
.green.opacity(0.05),
]
),
startPoint: .top,
endPoint: .bottom
)
AreaMark(
x: .value("Date", entry.date),
yStart: .value("Price", round(minY - ((maxY - minY) / 100) * 20)),
yEnd: .value("PriceEnd", entry.closePrice)
)
.interpolationMethod(.cardinal)
.foregroundStyle(curGradient)
.alignsMarkStylesWithPlotArea()
}
}
.chartLegend(position: .top, alignment: .center)
.chartYScale(domain: minY - ((maxY - minY) / 100) * 20...maxY + ((maxY - minY) / 100) * 20)
.chartXAxis
{
AxisMarks(values: .stride(by: .day))
{ date in
AxisGridLine()
AxisValueLabel(format: .dateTime.weekday(.narrow), centered: true)
}
}.chartYAxis {
AxisMarks(position: .leading)
}
}.frame(width: 347, height: 161.5)
It looks like you need to differentiate the data points being specified in the two ForEach
loops better. Maybe, Swift Charts thinks they are the same series, right now. For instance, you could explicitly set the series in your call to LineMark
using the (x:y:series:)
initializer, or by using the .foregroundStyle(by:)
modifier. Please see the "Plotting Multiple Lines" section of the LineMark
docs for examples.
Having said that, I see you are calling .foregroundStyle(:)
. I've not tried using that, in my Swift Charts travels, so I don't know if your result is expected. If you had provided a usable example, I could have verified. In future, please provide a minimal yet fully usable example in your questions. I would have dropped all the code about AreaMarks, Axes, etc from your code, and supplied some simple data so we could just copy and paste your code to reproduce the problem.