Add db command

This commit is contained in:
2024-11-09 01:16:31 +09:00
parent 7750faf8d0
commit bcbbd4c860
4 changed files with 88 additions and 15 deletions

View File

@@ -220,26 +220,44 @@ class CandleMinuteFileName {
extension KissConsole {
func collectCandleMinuteFiles() -> [String: [URL]] {
guard let enumerator = FileManager.subPathFiles("data") else {
func subPathForProduct(productNo: String?) -> FileManager.DirectoryEnumerator? {
if let productNo = productNo {
return FileManager.subPathFiles("data/\(productNo)")
}
else {
return FileManager.subPathFiles("data")
}
}
func collectCandleMinuteFiles(productNo: String?, year: String?, month: String?) -> [String: [URL]] {
guard let enumerator = subPathForProduct(productNo: productNo) else {
return [:]
}
let candleMinName = CandleMinuteFileName()
var allCandles = [String: [URL]]()
var candleFiles = [String: [URL]]()
for case let fileUrl as URL in enumerator {
guard let (productNo, _) = candleMinName.matchedUrl(fileUrl.path) else {
guard let (fileProductNo, yyyyMMdd) = candleMinName.matchedUrl(fileUrl.path) else {
continue
}
if let productNo = productNo, productNo != fileProductNo {
continue
}
if let year = year, yyyyMMdd.prefix(4) != year {
continue
}
if let month = month, yyyyMMdd.dropFirst(4).prefix(2) != month {
continue
}
if allCandles.keys.contains(productNo) {
allCandles[productNo]!.append(fileUrl)
if candleFiles.keys.contains(fileProductNo) {
candleFiles[fileProductNo]!.append(fileUrl)
}
else {
allCandles[productNo] = [fileUrl]
candleFiles[fileProductNo] = [fileUrl]
}
}
return allCandles
return candleFiles
}
func buildCandleMinuteDB(productNo: String, csvFiles: [URL], removeOldDB: Bool = false) {

View File

@@ -104,6 +104,9 @@ class KissConsole: KissMe.ShopContext {
//
case real = "real"
// DB1
case db = "db"
//
case news = "news"
case newsAll = "news all"
@@ -136,6 +139,8 @@ class KissConsole: KissMe.ShopContext {
return true
case .real:
return true
case .db:
return true
case .news, .newsAll:
return false
}
@@ -283,6 +288,8 @@ class KissConsole: KissMe.ShopContext {
case .test: onTest(args)
case .real: await onReal(args)
case .db: await onDB(args)
case .news: await onNews(args)
case .newsAll: onNewsAll(args)
@@ -1253,6 +1260,48 @@ extension KissConsole {
}
private func onDB(_ args: [String]) async {
guard args.count >= 3 else {
print("Missing options")
return
}
guard args[0] == "candle" else {
print("Missing candle or something")
return
}
switch args[1] {
case "build":
onDB_Build(Array(args.dropFirst(2)))
case "validate":
onDB_Validate(Array(args.dropFirst(2)))
case "count":
onDB_Count(Array(args.dropFirst(2)))
default:
onDB_Select(Array(args.dropFirst(2)))
}
}
private func onDB_Build(_ args: [String]) {
}
private func onDB_Validate(_ args: [String]) {
}
private func onDB_Count(_ args: [String]) {
}
private func onDB_Select(_ args: [String]) {
}
private func onNews(_ args: [String]) async {
guard args.count == 1, let day = args[0].yyyyMMdd_toDate else {
print("Missing day")

View File

@@ -52,14 +52,9 @@ struct DB1_CandleData_Tests: KissTestCase {
let csvFiles = Self.collectCsv(productNo: productNo, yyyy: year, MM: month)
let dataPath = URL.currentDirectory().appending(path: "data")
var itemCount = 0
for csvFile in csvFiles {
let candleMinName = CandleMinuteFileName()
if let (_, yyyyMMdd) = candleMinName.matchedUrl(csvFile.path), let year = Int(yyyyMMdd.prefix(4)) {
let yearDbPath = dataPath.appending(path: "\(productNo)/min/candle-\(year).db1")
}
let yearDbPath = dataPath.appending(path: "\(productNo)/min/candle-\(year).db1")
try? FileManager.default.removeItem(at: yearDbPath)
try? FileManager.default.createDirectory(at: yearDbPath, withIntermediateDirectories: true)
do {
@@ -74,6 +69,7 @@ struct DB1_CandleData_Tests: KissTestCase {
try db.insertData(item: item)
assertEqual(candleData.candle, candle)
itemCount += 1
}
try db.commit()
@@ -81,6 +77,7 @@ struct DB1_CandleData_Tests: KissTestCase {
print("\(error)")
}
}
Self.insertCount = itemCount
}
let test_5_CountSamsungDB: () -> Void = {
@@ -94,13 +91,17 @@ struct DB1_CandleData_Tests: KissTestCase {
let db = try KissDB(directory: yearDbPath)
try db.begin()
var itemCount = 0
try db.selectData(into: { (dataItem: KissDB.DataItem) -> Bool in
let candleData = CandleData(key: dataItem.key, data: dataItem.value)
assertEqual(String(candleData.candleDate.prefix(6)), yyyyMM)
itemCount += 1
return true
})
try db.rollback()
assertEqual(Self.insertCount, itemCount)
} catch {
print("\(error)")
}
@@ -109,6 +110,7 @@ struct DB1_CandleData_Tests: KissTestCase {
static let samsungProductNo = "005930"
static let year = "2023"
static let month = "06"
static var insertCount: Int = 0
static func collectCsv(productNo: String, yyyy: String, MM: String) -> [URL] {
guard let enumerator = FileManager.subPathFiles("data/\(productNo)") else {

View File

@@ -44,7 +44,7 @@ WIP `modify (PNO) (ONO) (가격) (수량)` | 주문 내역을 변경. (수량)
`look (상품명)` | (상품명) 에 해당되는 PNO 를 표시함.
`load index` | data/index-products.csv 로부터 전체 지수 상품을 로딩.
`update index` | **KRX 지수** 로부터 전체 지수 상품을 얻어서 **data/index-products.csv** 로 저장.
`holiday [yyyyMMdd]` | 휴장일 여부를 판단함. yyyymmDD 를 생략하면 오늘 날짜로 확인. **data/holiday.csv** 로 저장.
`holiday [yyyyMMdd]` | 휴장일 여부를 판단함. yyyyMMdd 를 생략하면 오늘 날짜로 확인. **data/holiday.csv** 로 저장.
WIP `showcase` | 추천 상품을 제안함.
`loves` | 관심 종목 전체를 열람. profile.json 에 저장된 관심 종목을 표시함.
`love (탭).(번호) (PNO)` | 관심 종목에 추가함. (번호) 를 지정하지 않으면 (탭) 마지막에 추가함.
@@ -52,6 +52,10 @@ WIP `showcase` | 추천 상품을 제안함.
`localize names` | csv field name 에 대해서 한글명을 제공하는 **data/localized-names.csv** 를 저장.
`localize (on/off)`| 앞으로 저장하는 모든 csv file 의 field 에 (on) 이면 한글명으로, (off) 이면 영문으로 저장.
`real (PNO) (on/off)` | 실시간 웹소켓을 접속하여 수신된 데이터를 기록합니다. (on) 이면 파일로 기록, (off) 이면 기록하지 않음.
`db candle build [PNO] [yyyy] [MM] [dd]` | PNO 의 csv 파일로부터 지정된 yyyy, MM, dd 날짜에 대해서만 DB 로 빌드. **data/(PNO)/min/candle-(yyyy).db1** 파일에 저장.
`db candle validate [PNO] [yyyy]` | PNO 의 yyyy DB에 기록된 분봉에 대해서 유효한지 검사.
`db candle count [PNO] [yyyy]` | PNO 의 yyyy DB에 기록된 분봉 갯수를 열람.
`db candle (PNO) [yyyyMMdd] [HH]` | PNO 의 yyyyMMdd 날짜의 HH 시간의 모든 분봉을 열람.
* PNO 는 `Product NO` 의 약자이고, 상품의 `단축코드` (shortCode) 와 동일합니다.
* ONO 는 `Order NO` 의 약자이고, 고유한 주문번호 입니다.