I tried,
- I set the y-axis very narrow to make small price movements appear normal, it didn't help
- API results checked they are fine
- Other Diagramtypes (Points/ Line...) didnt fix the problem
I'm only using the yAxis no need for xAxis
here my whole code
My ChartViewController
//
// ChartViewController.swift
// MCOS
//
// Created by Burhan Cankurt on 01.09.23.
//
import UIKit
import CorePlot
class ChartViewController: UIViewController, CPTScatterPlotDataSource, CPTScatterPlotDelegate, CPTAxisDelegate {
var ArrayStockClose: [(date: String, close: Double)] = []
@IBOutlet weak var graphHostingView: CPTGraphHostingView!
override func viewDidLoad() {
super.viewDidLoad()
chartViewStockClose(with: .fiveMinute)
}
func chartViewStockClose(with timeFrame: TimeFrame) {
print("chartViewStockClose called") // Debug
let fetcher = chartFetcherStockClose()
chartLoadStockClose(with: timeFrame, fetcher: fetcher) { [weak self] result in
print("chartLoadStockClose completion called") // Debug
switch result {
case .success(let data):
self?.ArrayStockClose = data
print("Daten im ViewController: \(data) und zählung \(data.count)")
DispatchQueue.main.async {
print("initializeGraph called") // Debug
// Hier können Sie Ihren Graphen initialisieren oder aktualisieren
self?.initializeGraph()
}
case .failure(let error):
print("Error fetching data: \(error)")
}
}
}
func initializeGraph() {
// Konfigurieren Sie die Ansicht und den Graphen
configureGraphView(for: graphHostingView, plotData: ArrayStockClose, delegate: self) // Angenommen, Sie haben eine Funktion namens configureGraphView
// Konfigurieren Sie den Plot
configurePlot(for: graphHostingView, dataSource: self, delegate: self) // Angenommen, Sie haben eine Funktion namens configurePlot
}
}
// Erweiterung für CorePlot Datenquelle und Delegat
extension ChartViewController {
func numberOfRecords(for plot: CPTPlot) -> UInt {
print("numberOfRecords called, count: \(ArrayStockClose.count)")
return UInt(ArrayStockClose.count)
}
func number(for plot: CPTPlot, field: UInt, record: UInt) -> Any? {
print("number called for field: \(field), record: \(record)")
switch CPTScatterPlotField(rawValue: Int(field)) {
case .X:
return NSNumber(value: record) // Da wir die X-Achse nicht verwenden, können wir einfach den Index verwenden
case .Y:
return NSNumber(value: ArrayStockClose[Int(record)].close)
default:
return nil
}
}
}
My ChartFetcherStockClose
//
// ChartFetcherStockClose.swift
// MCOS
//
// Created by Burhan Cankurt on 01.09.23.
//
import Foundation
import Foundation
class chartFetcherStockClose {
func fetch(url: URL, completion: @escaping (Result<[(date: String, close: Double)], Error>) -> Void) {
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else {
completion(.failure(NSError(domain: "No data", code: 0, userInfo: nil)))
return
}
do {
let decoder = JSONDecoder()
let stockData = try decoder.decode([StructStockClose].self, from: data)
// Sortiere die Datenpunkte nach dem Datum
let sortedStockData = stockData.sorted { $0.date < $1.date }
// Erstelle ein leeres Array, um die Ergebnisse zu speichern.
var resultArray: [(date: String, close: Double)] = []
// Durchlaufe jedes Element in sortedStockData.
for data in sortedStockData {
resultArray.append((date: data.date, close: data.close))
}
// Rufe den Completion Handler mit dem Ergebnis-Array auf.
completion(.success(resultArray))
} catch {
completion(.failure(error))
}
}
task.resume()
}
}// Class End
My ChartLoadStockClose
//
// ChartLoadStockClose.swift
// MCOS
//
// Created by Burhan Cankurt on 01.09.23.
//
import Foundation
enum TimeFrame {
case oneMinute
case fiveMinute
case fifteenMinute
case thirtyMinute
case oneHour
case fourHour
case oneDay
}
func chartLoadStockClose(with timeFrame: TimeFrame, fetcher: chartFetcherStockClose, completion: @escaping (Result<[(date: String, close: Double)], Error>) -> Void) {
let timeFrameParameter: String
switch timeFrame {
case .oneMinute: timeFrameParameter = "1min"
case .fiveMinute: timeFrameParameter = "5min"
case .fifteenMinute: timeFrameParameter = "15min"
case .thirtyMinute: timeFrameParameter = "30min"
case .oneHour: timeFrameParameter = "1hour"
case .fourHour: timeFrameParameter = "4hour"
case .oneDay: timeFrameParameter = "1day"
}
let url = URL(string: "https://financialmodelingprep.com/api/v3/historical-chart/\(timeFrameParameter)/AAPL?apikey=BLABLABLA")!
fetcher.fetch(url: url) { result in
switch result {
case .success(let data):
// Verwende nur die letzten 48 Datenpunkte
let filteredData = Array(data.suffix(48))
completion(.success(filteredData))
case .failure(let error):
completion(.failure(error))
}
}
}
My ChartConfigureGraphView
//
// ChartConfigureGraphView.swift
// MCOS
//
// Created by Burhan Cankurt on 01.09.23.
//
import CorePlot
import UIKit
func configureGraphView(for graphView: CPTGraphHostingView, plotData: [(date: String, close: Double)], delegate: CPTAxisDelegate) {
print("configureGraphView called") // Debug
graphView.allowPinchScaling = false
// Configure graph
let graph = CPTXYGraph(frame: graphView.bounds)
graph.plotAreaFrame?.masksToBorder = false
graphView.hostedGraph = graph
graph.backgroundColor = UIColor.black.cgColor
graph.paddingBottom = 40.0
graph.paddingLeft = 50.0
graph.paddingTop = 30.0
graph.paddingRight = 5.0
// Set plot space
let yMin = plotData.min(by: { $0.close < $1.close })?.close ?? 0
let yMax = plotData.max(by: { $0.close < $1.close })?.close ?? 0
print("yMin: \(yMin)") // Debug
print("yMax: \(yMax)") // Debug
let yRange = yMax - yMin
let paddingPercentage = 0.05
print("yRange: \(yRange)") // Debug
let yMinAdjusted = yMin - (yRange * paddingPercentage)
let yMaxAdjusted = yMax + (yRange * paddingPercentage)
print("yMinAdjusted: \(yMinAdjusted)") // Debug
print("yMaxAdjusted: \(yMaxAdjusted)") // Debug
guard let plotSpace = graph.defaultPlotSpace as? CPTXYPlotSpace else { return }
plotSpace.yRange = CPTPlotRange(locationDecimal: CPTDecimalFromDouble(yMinAdjusted), lengthDecimal: CPTDecimalFromDouble(yMaxAdjusted - yMinAdjusted))
// Configure axes
let axisSet = graph.axisSet as! CPTXYAxisSet
let axisTextStyle = CPTMutableTextStyle()
axisTextStyle.color = CPTColor.white()
axisTextStyle.fontName = "HelveticaNeue-Bold"
axisTextStyle.fontSize = 10.0
axisTextStyle.textAlignment = .center
if let x = axisSet.xAxis {
x.isHidden = true // Versteckt die X-Achse
}
if let y = axisSet.yAxis {
print("Configuring yAxis") // Debug
y.majorIntervalLength = NSNumber(value: Double((yMaxAdjusted - yMinAdjusted) / 10.0)) // Dynamically adjust the interval
y.minorTicksPerInterval = 5
y.labelTextStyle = axisTextStyle
y.axisConstraints = CPTConstraints(lowerOffset: 0.0)
y.delegate = delegate
}
}
My Struct
//
// Structs.swift
// MCOS
//
// Created by Burhan Cankurt on 01.09.23.
//
import Foundation
struct StructStockClose: Decodable {
let close: Double
let date: String
}
My ChartConfigurePlot
//
// ChartConfigurePlot.swift
// MCOS
//
// Created by Burhan Cankurt on 01.09.23.
//
import CorePlot
import UIKit
func configurePlot(for graphView: CPTGraphHostingView, dataSource: CPTScatterPlotDataSource, delegate: CPTScatterPlotDelegate) {
print("configurePlot called") // Debug
let plot = CPTScatterPlot()
let plotLineStile = CPTMutableLineStyle()
plotLineStile.lineJoin = .round
plotLineStile.lineCap = .round
plotLineStile.lineWidth = 2
plotLineStile.lineColor = CPTColor.white()
plot.dataLineStyle = plotLineStile
plot.curvedInterpolationOption = .catmullCustomAlpha
plot.interpolation = .curved
plot.identifier = "coreplot-graph" as NSCoding & NSCopying & NSObjectProtocol
guard let graph = graphView.hostedGraph else { return }
plot.dataSource = dataSource
plot.delegate = delegate
graph.add(plot, to: graph.defaultPlotSpace)
}
I solved the problem with the visulation the problem was no matter if u use the xAxis or not u need the timestamps after creating this code
MyDateHelpers
and using it in my ChartViewController here
the Visulation worked correct but now im facing a very strange problem, Timeframe 1Minute and 5 Minutes works correct but if use a Timeframe above 5Minute i receive this error
What did i tried?
Strange: if u reduce my datapoints from 48 to 20 as example i get the chart loaded on higher timeframe 15Minutes and when i reduce it to 10 it loads also higher timeframe chart 30 Minutes
Any ideas what the problem could be?