D27 - 用 Swift 和公开资讯,打造投资理财的 Apps { 三大法人成交比重实作.2 }

先制作出简单的一个 VC 上面显示取得的三大法人资料的日期。

拉出两个 Button、一个 state label、一个装载 pie chart view 的 container view。

这边需要了解三大法人成交金额的数据出来的时间,是在下午三点。而前面所做的每日市场成交资讯的公布时间,并不一定和三大法人成交金额同时出来(详细时间要测测看)。因为这样的时间差,有可能在你滑进三大法人页面时,取得的资料还在前一个交易日,但当下已经有现在交易日的台股总成交量金额。所以计算的时候,不可以拿最新的台股成交量当分母,一定要用拉取最新的三大法人资讯日期为 key,然後去查这个 key 的当日台股成交值是多少。

也因为有可能当下手机的时间和三大法人资料的日期不同,所以这个页面最上方的 Label 是用来显示资料的时间。

https://ithelp.ithome.com.tw/upload/images/20211007/20140622xoISUvENdo.png

资料的合并

从 csv 档来的资料有下面这六项

    case dealersForProprietary //自营商自行买卖
    case dealersHedge//自营商(避险)
    case securitiesInvestorForTrust//投信
    case foreignInvestorWithoutForeignDealer // 外资及陆资不含外资自营商
    case foreignDealers //外资自营商
    case total //总计

但是,我们要的是[自营商]、[投信]、[外资]、[总计] 这四项而已,所以数据要处理。

宣告一个专门用於这个 pie chart 的 data model

/// 只有三大法人,没有细项
enum ThreeMajorInvestorType {
    case dealers //自营商
    case securitiesInvestorForTrust //投信
    case foreign //外资
    case total //总计
}

class ThreeMajorInvestorInfo {
    
    let type : ThreeMajorInvestorType
    var totalBuy: Double = 0
    var totalSell: Double = 0
    var difference: Double = 0
    
    init(type: ThreeMajorInvestorType) {
        self.type = type
    }
    
    func getItemName() -> String {
        
        switch type {
        case .foreign:
            return "外资"
        case .dealers:
            return "自营"
        case .securitiesInvestorForTrust:
            return "投资"
        case .total:
            return "总合"
        }
    }
}

totalBuy, totalSell, difference 需要宣告成 var 的原因,是在合并的时候,我们要累加。

计算的 func 如下,在计算上,可以看到重复且类似的程序码,这边就让读都自行优化了

/// 取得三大法人 自营商的总和项目
    private func getDealerInfo(detailMajorInfos: [MajorInvestor]) -> ThreeMajorInvestorInfo {
        
        let info = ThreeMajorInvestorInfo(type: .dealers)
        
        for each in detailMajorInfos {
            
            // Dealer 自营商有两项 1.自行买卖 2.避险
            if each.typeString.contains("Dealer") {
                
                info.totalBuy += each.totalBuy
                info.totalSell += each.totalSell
                info.difference += each.difference
            }
        }
        
        return info
    }
    
    /// 取得三大法人 投信的总和项目
    private func getSecuritiesTrustCompany(detailMajorInfos: [MajorInvestor]) -> ThreeMajorInvestorInfo {
        
        let info = ThreeMajorInvestorInfo(type: .securitiesInvestorForTrust)
        
        for each in detailMajorInfos {
            
            // 投信
            if each.typeString.contains("Securities") {
                
                info.totalBuy += each.totalBuy
                info.totalSell += each.totalSell
                info.difference += each.difference
            }
        }
        
        return info
    }
    
    /// 取得三大法人 外资的总和项目
    private func getForeignInvestor(detailMajorInfos: [MajorInvestor]) -> ThreeMajorInvestorInfo {
        
        let info = ThreeMajorInvestorInfo(type: .foreign)
        
        for each in detailMajorInfos {
            
            // 外资
            if each.typeString.contains("Foreign") {
                
                info.totalBuy += each.totalBuy
                info.totalSell += each.totalSell
                info.difference += each.difference
            }
        }
        
        return info
    }
    
    /// 取得三大法人 total 的项目
    private func getTotalInfo(detailMajorInfos: [MajorInvestor]) -> ThreeMajorInvestorInfo {
        
        let info = ThreeMajorInvestorInfo(type: .total)
        
        for each in detailMajorInfos {
            if each.typeString.contains("Total") {
                
                info.totalBuy = each.totalBuy
                info.totalSell = each.totalSell
                info.difference = each.difference
            }
        }
        
        return info
    }
    
    /// 这边有可优化空间
    private func calculate(detailMajorInfos: [MajorInvestor]) -> TotalMajorInvestorInfo {
        
        let dealer = getDealerInfo(detailMajorInfos: detailMajorInfos)
        let securitiesTrustCompany = getSecuritiesTrustCompany(detailMajorInfos: detailMajorInfos)
        let foreign = getForeignInvestor(detailMajorInfos: detailMajorInfos)
        let total = getTotalInfo(detailMajorInfos: detailMajorInfos)
        
        let threeMajor = TotalMajorInvestorInfo(dealers: dealer, securitiesInvestorForTrust: securitiesTrustCompany, foreign: foreign, total: total)
        
        return threeMajor
    }

接着在 VC 加上一个 property

private var totalMajorInvestorInfo: TotalMajorInvestorInfo?

左边的按钮在计算完,把值赋於 totalMajorInvestorInfo

// MARK: - IBAction
    @IBAction func calculateButtonDidTap(_ sender: Any) {
        
        let threeMajorInvestors = calculate(detailMajorInfos: self.majorInvestors)
        self.totalMajorInvestorInfo = threeMajorInvestors
        
    }

可以再顺手做一下三大法人进出总金额的计算,并把结果放在 UI 上

private func updateCalculateUI() {
        
        var text = "计算完毕  "
        
        let unit = 100_000_000 //亿
        
        if let total = totalMajorInvestorInfo?.total {
            
            let item = total.getItemName()
            
            let buy = Int(total.totalBuy) / unit
            
            let sell = Int(total.totalSell) / unit
            
            let diff = Int(total.difference) / unit
            
            text += " \(item): - 买进:\(buy) 亿, 卖出:\(sell) 亿, 买卖差:\(diff) 亿,"
        }
        
        calculateLabel.text = text
    }

那 button 发动的程序码如下

// MARK: - IBAction
    @IBAction func calculateButtonDidTap(_ sender: Any) {
        
        let threeMajorInvestors = calculate(detailMajorInfos: self.majorInvestors)
        self.totalMajorInvestorInfo = threeMajorInvestors
        
        updateCalculateUI() // 和前面的 button 程序码比起来,只差这一行
    }

<<:  如果Pod应用程序出事情的话,还是做一下健康检查

>>:  [从0到1] C#小乳牛 练成基础程序逻辑 Day 22 - 泛型集合 List<T>

一 Ryu 大师: QoS

Purpose: Set the Queue to switch Queue 0 : Max ra...

Day24 Vue 认识Porps(3)

以物件做props的传递 我们先来看看一个例子! 在这里我们先用props把外层元件的data里的i...

第十五天:初探 Gradle properties

为了让 Gradle 在运行的时候可以更弹性,Gradle 支援一系列载入建置环境(Build En...

Day7-aws或gcp 我选择本机建立k8s

是否该用云端平台 在正式使用k8s的时候,部署k8s最好的情况是使用云端平台。 一来机器规格可以依照...

16. STM32-I²C EEPROM DataSheet

上一篇介绍过了I2C的基本原理以及相关的函数,这一篇会介绍EEPROM来做为I2C实作的示范。 什麽...