D23 - 用 Swift 和公开资讯,打造投资理财的 Apps { 台股成交量实作.3 }

在 KLineViewController 开出的 volumeDataSet 会在 parent vc 推进来前就设定好。

所以我们直接在 KLine VC 里面操作大盘量的 data 即可。

var volumeDataSet = [TwMarketTradingInfo]()

要让文字转成数字,要先开出 TwMarketTradingInfo 在 Charts 上用的属性

import Foundation

struct TwMarketTradingInfo: Hashable {
    
    let date: Date
    let tradeVolumeString: String
    let tradeValueString: String
    let transactionString: String
    let taiexString: String
    let changeString: String
    
    private var numberFormatter: NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter
    }
    
    var value: Double? {
        return numberFormatter.number(from: tradeValueString)?.doubleValue
    }
    
    var volume: Double? {
        return numberFormatter.number(from: tradeValueString)?.doubleValue
    }
    
    var transaction: Double? {
        return numberFormatter.number(from: transactionString)?.doubleValue
    }
    
    var taiex: Double? {
        return numberFormatter.number(from: taiexString)?.doubleValue
    }
    
    var change: Double? {
        return numberFormatter.number(from: changeString)?.doubleValue
    }
}

先进入 ChartsAdapter,我们要让 volumeDataList 转成 BarChartData

/// 取得大盘量的 Data
    private func getVolumeBarData(volumeDataList: [TwMarketTradingInfo]) -> BarChartData {
        
        var barDataEntryList = [BarChartDataEntry]()
        
        for (index, info) in volumeDataList.enumerated() {
            
            let y = info.volume ?? 0
            let dataEntry = BarChartDataEntry(x: Double(index), y: y)
            barDataEntryList.append(dataEntry)
        }
        
        let dataSet = BarChartDataSet(entries: barDataEntryList)
        dataSet.drawValuesEnabled = false //如果把数值也列出,图会非常的杂乱,而且值可以设定在右边
        dataSet.axisDependency = .right //左方的轴已经设定给加权指数了,所以量的图要设定在右边的轴
        
        let data = BarChartData(dataSet: dataSet)
        return data
    }

接着,修改 updateWithMALine 的接口,输入参数要扩充 volumeDataList

//原来的接口
// func updateWithMALine(stockSticks: [StockKLine], combinedView: UIView) {
// 扩充 volumeDataList
func updateWithMALine(stockSticks: [StockKLine], volumeDataList: [TwMarketTradingInfo], combinedView: UIView) {

然後在实作 combinedData 後,加上 barData

    func updateWithMALine(stockSticks: [StockKLine], volumeDataList: [TwMarketTradingInfo], combinedView: UIView) {
        
        if let combinedView = combinedView as? CombinedChartView {
            
            let ma5DataSet = getMALineData(stockSticks: stockSticks, range: 5, color: .blue)
            let ma10DataSet = getMALineData(stockSticks: stockSticks, range: 10, color: .red)
            let ma20DataSet = getMALineData(stockSticks: stockSticks, range: 20, color: .systemOrange)
            
            let lineData = LineChartData(dataSets: [ma5DataSet, ma10DataSet, ma20DataSet])
            let candleData = getCandleData(stockSticks: stockSticks)
            let barData = getVolumeBarData(volumeDataList: volumeDataList)
            
            let combinedData = CombinedChartData()
            combinedData.lineData = lineData
            combinedData.candleData = candleData
            combinedData.barData = barData
            
            combinedView.data = combinedData
            
            // 这边有优化空间,请读者自行优化
            let candleDataEntry = convert(stockStick: stockSticks)
            let dataSet = convert(dataEntry: candleDataEntry)
            updateMaxMin(combinedView, dataSet: dataSet)
            
            let indexDateLabels = getIndexDateLabels(from: stockSticks)
            updateXAxis(combinedView, indexDateLabels: indexDateLabels)
        }
    }

接下来,就去改 KLineViewController 的 setupCandleView()

    private func setupCandleView() {
        
        chartsAdapter.updateWithMALine(stockSticks: kLineDataSet, volumeDataList: volumeDataSet, combinedView: chartView)
    }

出来的结果就像这样子,还差了一点。

因为资料来源有告诉我们,当日涨还是跌,所以更好的表示,就是当那一天的大盘是涨的,Bar 就是红色,反之就是绿色。

https://ithelp.ithome.com.tw/upload/images/20211002/20140622DL4QpoF8YY.png

在 BarChartDataSet() 生出来之後,可以设定 [UIColor],去设定颜色。

再扩充 ChartsAdapter,让这个物件可以得到每一根 bar 的颜色

private func getBarColors(volumeList: [TwMarketTradingInfo]) -> [UIColor] {
    
        let colors = volumeList.map { info -> UIColor in
            
            let change = info.change ?? 0
            if change < 0 {
                return UIColor.systemGreen
            }
            return UIColor.systemRed
        }
        return colors
    }

然後,在从 getVolumeBarData 转成 DataSet 之後,加上 colors,就完成了。

/// 取得大盘量的 Data
    private func getVolumeBarData(volumeDataList: [TwMarketTradingInfo]) -> BarChartData {
        
        var barDataEntryList = [BarChartDataEntry]()
        
        for (index, info) in volumeDataList.enumerated() {
            
            let y = info.volume ?? 0
            let dataEntry = BarChartDataEntry(x: Double(index), y: y)
            barDataEntryList.append(dataEntry)
        }
        
        let dataSet = BarChartDataSet(entries: barDataEntryList)
        dataSet.drawValuesEnabled = false //如果把数值也列出,图会非常的杂乱,而且值可以设定在右边
        dataSet.axisDependency = .right //左方的轴已经设定给加权指数了,所以量的图要设定在右边的轴
        
        let colors = getBarColors(volumeList: volumeDataList) //加上颜色
        dataSet.colors = colors
        
        let data = BarChartData(dataSet: dataSet)
        return data
    }

Build 起来试试看。

https://ithelp.ithome.com.tw/upload/images/20211002/201406220pneUl1IZf.png

当当! 整个图被压缩!

我们得到了软件工程师的日常礼物「有 bug!」

我们下一篇来解决这个 Charts 没有照大脑中呈现的方式画的状况。


<<:  Day25-设定大风吹 使用复数values.yaml

>>:  MySQL汇入JS

9.MYSQL输出写入的内容

建立好自己完整的表格之後,就可以开始搜寻自己要的东西了 SELECT * (全部栏位) FROM 什...

电子书阅读器上的浏览器 [Day26] 保持画面不会自动关闭

今天的内容很短,因为实作还蛮容易的。 浏览网页时,有些时候是在看影片。这时,如果没有特别设定要系统保...

[Day29] AWS Wavelength (5G)

什麽是 Wavelength? Wavelength 将 5G 网路的高频宽和超低延迟与 AWS 运...

Day 15 - UML x Interface — Notifier

UML Notifier 的 UML 主要是根据 Ant Design 的设计画出来的,而在 Ma...

Day 28 - 到客户端执行弱点扫瞄并修复的心得分享 第十五天

今天是到客户端处理弱点的第15天,而铁人赛剩下倒数3天了。 继续加油下去中风险等级也快要修完了,今天...