Implement candle period
This commit is contained in:
@@ -10,6 +10,7 @@ import Foundation
|
||||
|
||||
public struct Domestic {
|
||||
public typealias Candle = MinutePriceResult.OutputPrice
|
||||
public typealias CandlePeriod = PeriodPriceResult.OutputPrice
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public enum MarketWarning: String, Codable {
|
||||
|
||||
|
||||
/// 기간분류코드
|
||||
public enum PeriodDivision: String, Codable {
|
||||
public enum PeriodDivision: String, Codable, CustomStringConvertible {
|
||||
/// 일봉
|
||||
case daily = "D"
|
||||
/// 주봉
|
||||
@@ -49,6 +49,15 @@ public enum PeriodDivision: String, Codable {
|
||||
case monthly = "M"
|
||||
/// 년봉
|
||||
case yearly = "Y"
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .daily: return "daily"
|
||||
case .weekly: return "weekly"
|
||||
case .monthly: return "monthly"
|
||||
case .yearly: return "yearly"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -543,6 +552,10 @@ public struct MinutePriceResult: Codable {
|
||||
case conclusionVolume = "cntg_vol"
|
||||
}
|
||||
|
||||
public var stockFullDate: String {
|
||||
return stockBusinessDate + stockConclusionTime
|
||||
}
|
||||
|
||||
public init(array: [String]) {
|
||||
self.stockBusinessDate = array[0]
|
||||
self.stockConclusionTime = array[1]
|
||||
@@ -562,7 +575,7 @@ public struct PeriodPriceResult: Codable {
|
||||
public let messageCode: String
|
||||
public let message: String
|
||||
public let output1: OutputSummary?
|
||||
public let output2: [OutputPrice]
|
||||
public let output2: [OutputPrice]?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case resultCode = "rt_cd"
|
||||
@@ -753,5 +766,21 @@ public struct PeriodPriceResult: Codable {
|
||||
case previousDayVariableRatio = "prdy_vrss"
|
||||
case revaluationIssueReason = "revl_issu_reas"
|
||||
}
|
||||
|
||||
public init(array: [String]) {
|
||||
self.stockBusinessDate = array[0]
|
||||
self.stockClosingPrice = array[1]
|
||||
self.stockOpenningPrice = array[2]
|
||||
self.highestStockPrice = array[3]
|
||||
self.lowestStockPrice = array[4]
|
||||
self.accumulatedVolume = array[5]
|
||||
self.accumulatedTradingAmount = array[6]
|
||||
self.exDivision = ExDivision(rawValue: array[7])!
|
||||
self.partitionRate = array[8]
|
||||
self.partitionModifiable = YesNo(rawValue: array[9])!
|
||||
self.previousDayVariableRatioSign = array[10]
|
||||
self.previousDayVariableRatio = array[11]
|
||||
self.revaluationIssueReason = array[12]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ extension KissConsole {
|
||||
}
|
||||
|
||||
static func writeShop(_ shopItems: [DomesticShop.Product], fileUrl: URL) {
|
||||
var stringCsv: String = ""
|
||||
var stringCsv = ""
|
||||
let header = "baseDate,shortCode,isinCode,marketCategory,itemName,corporationNo\n"
|
||||
stringCsv.append(header)
|
||||
for item in shopItems {
|
||||
@@ -83,8 +83,8 @@ extension KissConsole {
|
||||
}
|
||||
|
||||
static func writeCandle(_ prices: [Domestic.Candle], fileUrl: URL) {
|
||||
var stringCsv: String = "stockBusinessDate,stockConclusionTime,accumulatedTradingAmount,currentStockPrice,secondStockPrice,highestStockPrice,lowestStockPrice,conclusionVolume\n"
|
||||
let header = ""
|
||||
var stringCsv = ""
|
||||
let header = "stockBusinessDate,stockConclusionTime,accumulatedTradingAmount,currentStockPrice,secondStockPrice,highestStockPrice,lowestStockPrice,conclusionVolume\n"
|
||||
stringCsv.append(header)
|
||||
for item in prices {
|
||||
let stringItem = [item.stockBusinessDate,
|
||||
@@ -106,6 +106,35 @@ extension KissConsole {
|
||||
}
|
||||
}
|
||||
|
||||
static func writeCandle(_ prices: [Domestic.CandlePeriod], fileUrl: URL) {
|
||||
var stringCsv = ""
|
||||
let header = "stockBusinessDate,stockClosingPrice,stockOpenningPrice,highestStockPrice,lowestStockPrice,accumulatedVolume,accumulatedTradingAmount,exDivision,partitionRate,partitionModifiable,previousDayVariableRatioSign,previousDayVariableRatio,revaluationIssueReason\n"
|
||||
stringCsv.append(header)
|
||||
for item in prices {
|
||||
let stringItem = [item.stockBusinessDate,
|
||||
item.stockClosingPrice,
|
||||
item.stockOpenningPrice,
|
||||
item.highestStockPrice,
|
||||
item.lowestStockPrice,
|
||||
item.accumulatedVolume,
|
||||
item.accumulatedTradingAmount,
|
||||
item.exDivision.rawValue,
|
||||
item.partitionRate,
|
||||
item.partitionModifiable.rawValue,
|
||||
item.previousDayVariableRatioSign,
|
||||
item.previousDayVariableRatio,
|
||||
item.revaluationIssueReason].joined(separator: ",")
|
||||
stringCsv.append(stringItem)
|
||||
stringCsv.append("\n")
|
||||
}
|
||||
do {
|
||||
try stringCsv.write(toFile: fileUrl.path, atomically: true, encoding: .utf8)
|
||||
print("wrote \(fileUrl.lastPathComponent) with \(prices.count)")
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum CandleValidation: CustomStringConvertible {
|
||||
case ok
|
||||
|
||||
@@ -60,16 +60,37 @@ extension KissConsole {
|
||||
defer {
|
||||
currentCandleShortCode = nil
|
||||
}
|
||||
|
||||
var nextTime = Date()
|
||||
var candles = [Domestic.Candle]()
|
||||
|
||||
var nextTime = startDate
|
||||
var candles = [Domestic.CandlePeriod]()
|
||||
var count = 0
|
||||
|
||||
let result = try await account!.getPeriodPrice(productNo: productNo, startDate: startDate, endDate: endDate, period: .daily)
|
||||
while true {
|
||||
count += 1
|
||||
|
||||
let result = try await account!.getPeriodPrice(productNo: productNo, startDate: startDate, endDate: endDate, period: period)
|
||||
|
||||
if let prices = result.output2, prices.isEmpty == false {
|
||||
candles.append(contentsOf: prices)
|
||||
if let last = prices.last {
|
||||
|
||||
// TODO: nextTime 갱신을 처리한다...
|
||||
}
|
||||
try await Task.sleep(nanoseconds: 1_000_000_000 / PreferredCandleTPS)
|
||||
}
|
||||
else {
|
||||
print("\(period) price finished")
|
||||
}
|
||||
}
|
||||
|
||||
// let fileUrl = candleFileUrl(productNo: productNo, period: "min", day: minTime)
|
||||
// KissConsole.writeCandle(candles, fileUrl: fileUrl)
|
||||
candles.sort(by: { $0.stockBusinessDate > $1.stockBusinessDate })
|
||||
guard let maxTime = candles.first?.stockBusinessDate else {
|
||||
print("No price items")
|
||||
return false
|
||||
}
|
||||
|
||||
let fileUrl = candleFileUrl(productNo: productNo, period: period.filePeriod, day: maxTime)
|
||||
KissConsole.writeCandle(candles, fileUrl: fileUrl)
|
||||
return true
|
||||
} catch {
|
||||
print(error)
|
||||
@@ -125,13 +146,13 @@ extension KissConsole {
|
||||
}
|
||||
}
|
||||
|
||||
candles.sort(by: { $0.stockBusinessDate < $1.stockBusinessDate })
|
||||
guard let minTime = candles.first?.stockBusinessDate else {
|
||||
candles.sort(by: { $0.stockFullDate > $1.stockFullDate })
|
||||
guard let maxTime = candles.first?.stockBusinessDate else {
|
||||
print("No price items")
|
||||
return false
|
||||
}
|
||||
|
||||
let fileUrl = candleFileUrl(productNo: productNo, period: .minute, day: minTime)
|
||||
let fileUrl = candleFileUrl(productNo: productNo, period: .minute, day: maxTime)
|
||||
KissConsole.writeCandle(candles, fileUrl: fileUrl)
|
||||
return true
|
||||
} catch {
|
||||
@@ -140,3 +161,16 @@ extension KissConsole {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension PeriodDivision {
|
||||
var filePeriod: KissConsole.CandleFilePeriod {
|
||||
switch self {
|
||||
case .daily: return .day
|
||||
case .weekly: return .weak
|
||||
case .monthly: assertionFailure()
|
||||
case .yearly: assertionFailure()
|
||||
}
|
||||
return .minute
|
||||
}
|
||||
}
|
||||
|
||||
2
bin/data
2
bin/data
Submodule bin/data updated: d102289c45...08024e32ce
Reference in New Issue
Block a user