D18 - 用 Swift 和公开资讯,打造投资理财的 Apps { 移动平均线(MA线)实作.1 }

"The shortest distance between two points is a straight line." - Archimedes

要做出移动平均线,在 Charts 里面最直观拿来达成这个任务用的物件,就是 LineCartView。但这个物件只能吃 LineChartData 的资料。我们要做的是在图上,同时呈现 K 线和均线,同时,也不排除新的陨石级需求砸下来的状况。所以,我们要使用的类别就是 CombinedChartView。CombinedChartView 里面的 Data 可以塞 candleData, lineData 未来有 barData 也是塞的进去。

step1 - 先宣告「点」这个概念的物件

import Foundation

/// MA 线的点
struct MovingAveragePoint {
    
    let x: Double
    let y: Double
}

step2 - 宣告专门处理移动平均线计算的物件

这个物件专门处理 SockKLine array → MovingAveragePoint Array

注意,里面有个处理五个收盘价总合的地方。如果读者会 dynamic programming 的手法,当总合往前算的时候,减去最後一根 k 棒的收盘价,再加上前一根 k 棒的收盘价。理论上来说,效能会比较好。

但我现在在赶稿和赶专案的状态,所以这一段的优化就留给读者进行了。

import Foundation

/// 专门处理移动平均线的物件
struct MovingAverageUtility {
    
    /// 将已得到的 K 棒,转出 5 MA 的资料
    /// - Parameter stockTicks: 传入的 K 棒需先保证 date 从远排到近
    /// - Returns: 回传的 MA 点也保证会是 x 从小排到大
    func get5MAPoints(from stockTicks: [StockKLine]) -> [MovingAveragePoint] {
        
        let maPeriod = 5 // 5MA
        
        let tickIndices = Array(stockTicks.indices).sorted { $0 > $1 } // 先拿出 index 并把 index 从大到小排
        
        var maPoints = [MovingAveragePoint]()
        
        for tickIndex in tickIndices {

            let startIndex = tickIndex - 5 + 1
            
            if !stockTicks.indices.contains(startIndex) || !stockTicks.indices.contains(tickIndex) {
                break
            }
            
            let needCalculateTicks = Array(stockTicks[startIndex...tickIndex])
            
            // 从这里开始计算 n 日内收盘价的平均,有更有效率的做法,像是动态规画的方式实作。这一段就留给读者自行优化
            let closePriceList = needCalculateTicks.map { tick in
                
                return tick.close ?? 0 // 这边先不考虑如果没有收盘价(暂停交易)的情况,如果有,应该把这个点去除掉,使用 filter 即可
            }
            
            let sum = closePriceList.reduce(0, +) //总合
            let maValue = sum / Double(maPeriod)
            
            let point = MovingAveragePoint(x: Double(tickIndex), y: maValue)
            maPoints.append(point)
        }
        
        return maPoints.sorted { $0.x < $1.x }
    }
}

当做出 MA Point 物件,和专门处理 MA 计算的工具,剩下的就是在 CandleStickData 算完後,把 K 线资料丢进 MA 计算工具,就会得到 LineChartData 了。

台股申购日历
IT铁人赛Demo App

下方是这次 D1 ~ D12 的完成品,可以下载来试
App Store - 台股申购日历

https://ithelp.ithome.com.tw/upload/images/20210924/20140622ypOBM0tgrZ.png


<<:  D27-(9/27)-长兴(1717)-化学传产的好公司

>>:  sed - 5 Replace command

DAY28 linebot message api-Template 介绍-1

传送样板(Template) 样板有四种,分别是 Confirm、Buttons、Carousel、...

Day8 区块元素与行内元素

网页容器概念 网页上的内容可以被分为排版用的容器(ex: <div> )与元素(ex:...

USB Type-C的工作原理与技术分析

USB Type-C的工作原理与技术分析 (一) USB 3.1 基本规格 图1.历代USB规格 ↑...

资料抽象与封装(Data Abstraction vs Encapsulation)

人们经常会被资料抽象和封装混淆,把抽象的概念当作封装或信息隐藏。事实并非如此。以下定义来自 ISO/...

【从实作学习ASP.NET Core】Day20 | 前台 | 建立前台页面

今天要完成商店的主要页面,基本上都是前端的工作,就是让网页看起来比较像样啦 但因为这方面我自己也不是...