目标: 做出台湾加权指数 K 线图
之前做出来的台股申购是独立的功能,为了不影响前面已经完成的功能,所以开一个新的 VC 进行 K 线实作。架构一样,遵照 Apple 的 MVC 规范。
先开 Model
import Foundation
class TwStockMarketKLineModel {
}
然後再开 VC
import UIKit
class TwStockMarketKLineViewController: UIViewController {
private lazy var model: TwStockMarketKLineModel = {
let model = TwStockMarketKLineModel()
return model
}()
override func viewDidLoad() {
super.viewDidLoad()
}
}
如果你不想让 storyboard 上的 VC 太多,那你可以让一系列相关的 VC 在一个 storyboard 上。所以我们另外开一个 storyboard 来放这个 VC。
K 线的拿取网址如下
加权指数-公开资讯观测站 https://www.twse.com.tw/zh/page/trading/indices/MI_5MINS_HIST.html
加权指数的 K 线的 csv 档位址
https://www.twse.com.tw/en/indicesReport/MI_5MINS_HIST?response=csv&date=20210907
因为加权指数的栏位和申购资讯相比少很多,而且我只需要[日期] [开] [高] [低] [收] 而已,所以就直接拿英文版的资料,减少转换 Big5 的步骤。
因为需要 date=20210907 这一种日期格式,所以需要扩充 DateUtility 功能。
// 扩充在 DateUtility 里面,在拿取 K 线的时候要输入这个值
func getString(date: Date, format: String = "yyyy-MM-dd") -> String {
DateUtility.dateFormatter.calendar = isoCalendar
DateUtility.dateFormatter.dateFormat = format
return DateUtility.dateFormatter.string(from: date)
}
然後再新建一个 TwStockKLineManager
import Foundation
//加权指数-公开资讯观测站 https://www.twse.com.tw/zh/page/trading/indices/MI_5MINS_HIST.html
// https://www.twse.com.tw/en/indicesReport/MI_5MINS_HIST?response=csv&date=20210907
class TwStockKLineManager {
private var dateUtility: DateUtility {
return DateUtility()
}
private lazy var alamofireAdapter: AlamofireAdapter = {
return AlamofireAdapter()
}()
func requestTwStockKLine(date: Date, completion: @escaping ((Result<String, Error>) -> Void)) {
let format = "yyyyMMdd"
let string = dateUtility.getString(date: date, format: format)
let urlString = "https://www.twse.com.tw/en/indicesReport/MI_5MINS_HIST?response=csv&date=\(string)"
alamofireAdapter.requestForString(urlString, method: .get) { result in
switch result {
case .success(let string):
completion(.success(string))
case .failure(let error):
completion(.failure(error))
}
}
}
}
这样,专案中的任何物件,只要呼叫 requestTwStockKLine ,就可以拿到加权指数的 csv 档。
我们先看一下载的 URL 和拿到的资料,可以看到後面的 date 需要输入的格式是 yyyyMMdd
https://www.twse.com.tw/en/indicesReport/MI_5MINS_HIST?response=csv&date=20210907
所得到的 response CSV 档,用 Number 或 Excel 打开会长这样。
分析:
如同之前 [台股申购实作.4] 所提到的。千万不要自己手动转换历法。千万不要自己手动转换历法!!千万不要自己手动转换历法!!!!
「正常来说」,每个月的月份天数,有 28 天,29 天,30 天,31 天。所以当下的日期减去 31 天,就绝对不会在这个月,也不能保证就会是「上个月」,如果真的这样实作,会有可能出现意料之外的日期。所以,请用 Foundation 中的功能,去找上个月的日期,这比自己写日期转换的错误率低非常非常多。
在 DateUtility 扩充 func,输入 Date,可以得到输入 Date 当月的第一天 Date
//得到这个月第一天的 Date
func getStartOfMonth(date: Date = Date()) -> Date {
let calendar = isoCalendar
let startDate = isoCalendar.startOfDay(for: date)
return calendar.date(from: calendar.dateComponents([.year, .month], from: startDate)) ?? Date()
}
而 Foundation 的 Date 相关操作中,就有能对某个 DateComponent 进行加减操作的 API。
Apple 说明文件 https://developer.apple.com/documentation/foundation/calendar/2293453-date
程序码
/// Returns a new `Date` representing the date calculated by adding an amount of a specific component to a given date.
///
/// - parameter component: A single component to add.
/// - parameter value: The value of the specified component to add.
/// - parameter date: The starting date.
/// - parameter wrappingComponents: If `true`, the component should be incremented and wrap around to zero/one on overflow, and should not cause higher components to be incremented. The default value is `false`.
/// - returns: A new date, or nil if a date could not be calculated with the given input.
@available(iOS 8.0, *)
public func date(byAdding component: Calendar.Component, value: Int, to date: Date, wrappingComponents: Bool = false) -> Date?
所以,得到上个月第一天的 Date,就是先呼叫 getStartOfMonth(),取得当月第一天後,再用 dateComponent 的计算,拿取上个月第一天。
//取得输入 Date 的前一个月的第一天 Date
func getLastMonthStartDate(date: Date = Date()) -> Date {
let calendar = isoCalendar
let startOfMonth = getStartOfMonth(date: date)
return calendar.date(byAdding: DateComponents(month: -1), to: startOfMonth) ?? Date()
}
这样,完成了 Model 在拿取台股加权指数资料的时候,只要使用 DateUtility 的 func 就可以得到要输入的 Date。
>>: DAY11 - 第一个小范例 : LineBot 自动回话
今日目标 学习了解 Python Pandas 资料存取与运用视觉化呈现数据 DataFrame 资...
今天就来说说 setValue 与 patchValue 差异这部份吧 一开始不太能理解这 setV...
记录学习内容。看网路上大大们的文章和影片,做些纪录。 还不了解,内容可能有错误。 Longest I...
前言 有了这些功能後,想要知道能不能跑所有的股票,然後做这些事情,无论是行情订阅,还是历史资料。因此...
今天开始做我们的 Telegram Bot! Telegram Telegram 是一个通讯软件,就...