使用Yahoo Finance API和Alamofire获取股票价格,然后将其绘制在图表上

时间:2017-07-10 11:27:16

标签: swift graph alamofire yahoo-finance

我试图从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()

}


}

请帮忙,以便我可以把股票价格直接放到图表中。

0 个答案:

没有答案