我试图从Yahoo Finance API获取股票价格,然后将其绘制在图表上。我有从雅虎获取股票价格的功能,但我需要转换它们以便它可以被图表使用。我正在使用SwiftChart Cocoapod用于图表,并且在他们使用pod的示例中,他们有一个部分,它从.json文件中获取Apple股票的价格,然后将其解析为图表。我需要将Yahoo数据转换为相同的格式,以便将其放入图表中。
这是获取雅虎财经股票的代码:
//获取股票图表点
func fetchChartPoints(symbol: String, range: ChartTimeRange, completion:@escaping (_ chartPoints: [ChartPoint]) -> ()) {
DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
//An Alamofire regular responseJSON wont parse the JSONP with a callback wrapper correctly, so lets work around that.
let chartURL = SwiftStockGraphKit.chartUrlForRange(symbol, range: range)
Alamofire.request(chartURL, method: .get).responseData { response in
if let data = response.result.value {
var jsonString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)!
jsonString = jsonString.substring(from: 30) as NSString
jsonString = jsonString.substring(to: jsonString.length-1) as NSString
if let data = jsonString.data(using: String.Encoding.utf8.rawValue) {
if let resultJSON = (try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions(rawValue: 0))) as? [String : AnyObject] {
let series = resultJSON["series"] as! [[String : AnyObject]]
var chartPoints = [ChartPoint]()
for dataPoint in series {
//GMT off by 5 hrs
let date = NSDate(timeIntervalSince1970: (dataPoint["Timestamp"] as? Double ?? dataPoint["Date"] as! Double) - 18000.0)
chartPoints.append(
ChartPoint(
date: date as Date,
volume: dataPoint["volume"] as? Int,
open: dataPoint["open"] as? CGFloat,
close: dataPoint["close"] as? CGFloat,
low: dataPoint["low"] as? CGFloat,
high: dataPoint["high"] as? CGFloat
)
)
}
DispatchQueue.main.async() {
completion(chartPoints)
}
}
}
}
}
}
}
//
// Graph Time Frame
//
class func chartUrlForRange(_ symbol: String, range: ChartTimeRange) -> String {
var timeString = String()
switch (range) {
case .oneDay:
timeString = "1d"
case .fiveDays:
timeString = "5d"
case .tenDays:
timeString = "10d"
case .oneMonth:
timeString = "1m"
case .threeMonths:
timeString = "3m"
case .oneYear:
timeString = "1y"
case .fiveYears:
timeString = "5y"
}
return "http://chartapi.finance.yahoo.com/instrument/1.0/\(symbol)/chartdata;type=quote;range=\(timeString)/json"
}
然后,这是SwiftCharts用于获取JSON文件并将其转换为图形的代码:
import UIKit
import SwiftChart
class StockChartViewController: UIViewController, ChartDelegate {
var selectedChart = 0
@IBOutlet weak var labelLeadingMarginConstraint: NSLayoutConstraint!
@IBOutlet weak var label: UILabel!
@IBOutlet weak var chart: Chart!
fileprivate var labelLeadingMarginInitialConstant: CGFloat!
override func viewDidLoad() {
labelLeadingMarginInitialConstant = labelLeadingMarginConstraint.constant
initializeChart()
}
func initializeChart() {
chart.delegate = self
// Initialize data series and labels
let stockValues = getStockValues()
var serieData: [Float] = []
var labels: [Float] = []
var labelsAsString: Array<String> = []
// Date formatter to retrieve the month names
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM"
for (i, value) in stockValues.enumerated() {
serieData.append(value["close"] as! Float)
// Use only one label for each month
let month = Int(dateFormatter.string(from: value["date"] as! Date))!
let monthAsString:String = dateFormatter.monthSymbols[month - 1]
if (labels.count == 0 || labelsAsString.last != monthAsString) {
labels.append(Float(i))
labelsAsString.append(monthAsString)
}
}
let series = ChartSeries(serieData)
series.area = true
// Configure chart layout
chart.lineWidth = 0.5
chart.labelFont = UIFont.systemFont(ofSize: 12)
chart.xLabels = labels
chart.xLabelsFormatter = { (labelIndex: Int, labelValue: Float) -> String in
return labelsAsString[labelIndex]
}
chart.xLabelsTextAlignment = .center
chart.yLabelsOnRightSide = true
// Add some padding above the x-axis
chart.minY = serieData.min()! - 5
chart.add(series)
}
// Chart delegate
func didTouchChart(_ chart: Chart, indexes: Array<Int?>, x: Float, left: CGFloat) {
if let value = chart.valueForSeries(0, atIndex: indexes[0]) {
let numberFormatter = NumberFormatter()
numberFormatter.minimumFractionDigits = 2
numberFormatter.maximumFractionDigits = 2
label.text = numberFormatter.string(from: NSNumber(value: value))
// Align the label to the touch left position, centered
var constant = labelLeadingMarginInitialConstant + left - (label.frame.width / 2)
// Avoid placing the label on the left of the chart
if constant < labelLeadingMarginInitialConstant {
constant = labelLeadingMarginInitialConstant
}
// Avoid placing the label on the right of the chart
let rightMargin = chart.frame.width - label.frame.width
if constant > rightMargin {
constant = rightMargin
}
labelLeadingMarginConstraint.constant = constant
}
}
func didFinishTouchingChart(_ chart: Chart) {
label.text = ""
labelLeadingMarginConstraint.constant = labelLeadingMarginInitialConstant
}
func didEndTouchingChart(_ chart: Chart) {
}
func getStockValues() -> Array<Dictionary<String, Any>> {
// Read the JSON file
let filePath = Bundle.main.path(forResource: "AAPL", ofType: "json")!
let jsonData = try? Data(contentsOf: URL(fileURLWithPath: filePath))
let json: NSDictionary = (try! JSONSerialization.jsonObject(with: jsonData!, options: [])) as! NSDictionary
let jsonValues = json["quotes"] as! Array<NSDictionary>
// Parse data
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let values = jsonValues.map { (value: NSDictionary) -> Dictionary<String, Any> in
let date = dateFormatter.date(from: value["date"]! as! String)
let close = (value["close"]! as! NSNumber).floatValue
return ["date": date!, "close": close]
}
return values
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// Redraw chart on rotation
chart.setNeedsDisplay()
}
}
请帮忙,以便我可以把股票价格直接放到图表中。