diff --git a/KissMe/Sources/Common/Foundation+Extensions.swift b/KissMe/Sources/Common/Foundation+Extensions.swift index b1d3b03..e9bba31 100644 --- a/KissMe/Sources/Common/Foundation+Extensions.swift +++ b/KissMe/Sources/Common/Foundation+Extensions.swift @@ -40,6 +40,20 @@ extension Date { extension String { + public var yyyyMMdd: (Int, Int, Int)? { + guard utf8.count == 8 else { + return nil + } + let mmStartIndex = index(startIndex, offsetBy: 4) + let mmEndIndex = index(mmStartIndex, offsetBy: 2) + guard let hh = Int(String(prefix(4))), + let mm = Int(self[mmStartIndex.. Date? { + let sets: Set = [.year, .month, .day, .hour, .minute, .second] + var components = Calendar.current.dateComponents(sets, from: self) + components.timeZone = TimeZone(abbreviation: timeZone) + components.year = year + components.month = month + components.day = day + return Calendar.current.date(from: components) + } + + public mutating func change(year: Int, month: Int, day: Int, timeZone: String = "KST") { + if let newDate = changing(year: year, month: month, day: day, timeZone: timeZone) { + self = newDate + } + } } diff --git a/KissMeConsole/Sources/KissConsole+CSV.swift b/KissMeConsole/Sources/KissConsole+CSV.swift index 8f37460..dfb9df7 100644 --- a/KissMeConsole/Sources/KissConsole+CSV.swift +++ b/KissMeConsole/Sources/KissConsole+CSV.swift @@ -35,7 +35,7 @@ extension KissConsole { } func writeCandle(_ prices: [MinutePriceResult.OutputPrice], fileUrl: URL) { - var stringCsv: String = "stockBusinessDate,stockConclusionTime,accumulatedTradingAmount,currentStockPrice,secondStockPrice,highestStockPrice,lowestStockPrice,conclusionVolume" + var stringCsv: String = "stockBusinessDate,stockConclusionTime,accumulatedTradingAmount,currentStockPrice,secondStockPrice,highestStockPrice,lowestStockPrice,conclusionVolume,\n" let header = "" stringCsv.append(header) for item in prices { diff --git a/KissMeConsole/Sources/KissConsole.swift b/KissMeConsole/Sources/KissConsole.swift index 3ece378..8d47997 100644 --- a/KissMeConsole/Sources/KissConsole.swift +++ b/KissMeConsole/Sources/KissConsole.swift @@ -17,6 +17,7 @@ class KissConsole { private var productsLock = NSLock() private var products = [String: [DomesticShop.Product]]() private var currentShortCode: String? + private var currentCandleShortCode: String? private enum KissCommand: String { case quit = "quit" @@ -434,43 +435,72 @@ extension KissConsole { return } - do { - var nextTime = Date() - nextTime.change(hour: 17, min: 0, sec: 0) - - var candles = [MinutePriceResult.OutputPrice]() - var count = 0 - - while count < 3 { - let more = (count > 0) - count += 1 - print("minute price \(productNo) from \(nextTime.yyyyMMdd_HHmmss_forTime) \(more)") - let result = try await account!.getMinutePrice(productNo: productNo, startTodayTime: nextTime, more: more) + Task { + do { + guard currentCandleShortCode == nil else { + print("Already candle collecting") + return + } + currentCandleShortCode = productNo + defer { + currentCandleShortCode = nil + } - if let prices = result.output2 { - candles.append(contentsOf: prices) - if let last = prices.last { - if let (hh, mm, ss) = last.stockConclusionTime.HHmmss { - print("next: \(last.stockConclusionTime) / \(hh) \(mm) \(ss)") - nextTime.change(hour: hh, min: mm-1, sec: ss) + var nextTime = Date() + //nextTime.change(hour: 17, min: 0, sec: 0) + //nextTime.change(year: 2023, month: 5, day: 26) + //nextTime.change(hour: 9, min: 1, sec: 0) + + var candles = [MinutePriceResult.OutputPrice]() + var count = 0 + + while true { + let more = (count > 0) + count += 1 + print("minute price \(productNo) from \(nextTime.yyyyMMdd_HHmmss_forTime) \(more)") + let result = try await account!.getMinutePrice(productNo: productNo, startTodayTime: nextTime, more: more) + + if let prices = result.output2, prices.isEmpty == false { + candles.append(contentsOf: prices) + if let last = prices.last { + if nextTime.yyyyMMdd != last.stockBusinessDate { + if let (yyyy, mm, dd) = last.stockBusinessDate.yyyyMMdd { + print("next: \(last.stockBusinessDate)") + nextTime.change(year: yyyy, month: mm, day: dd) + } + } + if let (hh, mm, ss) = last.stockConclusionTime.HHmmss { + print("next: \(last.stockConclusionTime) / \(hh) \(mm) \(ss)") + nextTime.change(hour: hh, min: mm-1, sec: ss) + if hh == 9, mm == 0, ss == 0 { + print("minute price finished") + break + } + } } + /// Limit to request queries with 5 tps + try await Task.sleep(nanoseconds: 200_000_000) + } + else { + print("minute price finished") + break } } + + candles.sort(by: { $0.stockBusinessDate < $1.stockBusinessDate }) + guard let minTime = candles.first?.stockBusinessDate else { + print("No price items") + return + } + + let subPath = "data/\(productNo)" + let subFile = "\(subPath)/candle-\(minTime).csv" + let fileUrl = URL.currentDirectory().appending(path: subFile) + createSubpath(subPath) + writeCandle(candles, fileUrl: fileUrl) + } catch { + print("\(error)") } - - candles.sort(by: { $0.stockBusinessDate < $1.stockBusinessDate }) - guard let minTime = candles.first?.stockBusinessDate else { - print("No price items") - return - } - - let subPath = "data/\(productNo)" - let subFile = "\(subPath)/candle-\(minTime).csv" - let fileUrl = URL.currentDirectory().appending(path: subFile) - createSubpath(subPath) - writeCandle(candles, fileUrl: fileUrl) - } catch { - print("\(error)") } }