diff --git a/KissMe/Sources/Domestic/KRX300/DomesticIndex.swift b/KissMe/Sources/Domestic/KRX300/DomesticIndex.swift new file mode 100644 index 0000000..25f8831 --- /dev/null +++ b/KissMe/Sources/Domestic/KRX300/DomesticIndex.swift @@ -0,0 +1,163 @@ +// +// DomesticIndex.swift +// KissMe +// +// Created by ened-book-m1 on 2023/06/26. +// + +import Foundation + + +extension DomesticExtra { + + public enum IndexType: String { + case krx = "01" + case kospi = "02" + case kosdaq = "03" + case theme = "04" + } + + public enum ShareType: Int { + case unitOne = 1 + case unitThousand = 2 + case unitMiliion = 3 + } + + public enum MoneyType: Int { + case moneyWon = 1 + case moneyThounsand = 2 + case moneyMillion = 3 + case moneyBillion = 4 + } + + /// 한국거래소 - 주가지수 - 전체지수 시세 + /// + public struct IndexPriceRequest: KrxRequest { + public typealias KResult = String + + public var domain: String { + "http://data.krx.co.kr" + } + public var url: String { + "/comm/bldAttendant/getJsonData.cmd" + } + public var method: Method { .post } + + public var header: [String : String?] { + [:] + } + public var body: [String: Any] { + return [ + "idxIndMidclssCd": indexType.rawValue, + "strtDd": range.startDate.yyyyMMdd, + "endDd": range.endDate.yyyyMMdd, + "share": shareType.rawValue, + "money": moneyType.rawValue, + "csvxls_isNo": false, + "bld": "dbms/MDC/STAT/standard/MDCSTAT00201" + ] + } + public var result: KResult? = nil + + + struct DataRange { + let startDate: Date // yyyyMMdd + let endDate: Date // yyyyMMdd + } + let range: DataRange + let indexType: IndexType + let shareType: ShareType + let moneyType: MoneyType + + init(range: DataRange, indexType: IndexType) { + self.range = range + self.indexType = indexType + self.shareType = .unitOne + self.moneyType = .moneyWon + } + } + + + /// 한국거래소 - 주가지수 - 지수구성종목 + /// + public struct IndexPortfolioRequest: KrxRequest { + public typealias KResult = String + + public var domain: String { + "http://data.krx.co.kr" + } + public var url: String { + "/comm/bldAttendant/getJsonData.cmd" + } + public var method: Method { .post } + + public var header: [String : String?] { + [:] + } + + public var body: [String: Any] { + return [ + "idxIndMidclssCd": indexType.rawValue, + "trdDb": date.yyyyMMdd, + "share": shareType.rawValue, + "money": moneyType.rawValue, + "csvxls_isNo": false, + "bld": "dbms/MDC/STAT/standard/MDCSTAT00601" + ] + } + public var result: KResult? = nil + + + let indexType: IndexType + let date: Date + let shareType: ShareType + let moneyType: MoneyType + + init(indexType: IndexType, date: Date) { + self.indexType = indexType + self.date = date + self.shareType = .unitOne + self.moneyType = .moneyWon + } + } +} + + +extension KissAccount { + + /// 전체지수 시세 가져오기 + /// + static public func getIndexPrice(indexType: DomesticExtra.IndexType, startDate: Date, endDate: Date) async throws -> String { + return try await withUnsafeThrowingContinuation { continuation in + + let range = DomesticExtra.IndexPriceRequest.DataRange(startDate: startDate, endDate: endDate) + + let request = DomesticExtra.IndexPriceRequest(range: range, indexType: indexType) + request.query { result in + switch result { + case .success(let result): + continuation.resume(returning: (result)) + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + + /// 지수구성종목 가져오기 + /// + static public func getIndexPortfolio(indexType: DomesticExtra.IndexType, date: Date) async throws -> String { + return try await withUnsafeThrowingContinuation { continuation in + + let request = DomesticExtra.IndexPortfolioRequest(indexType: indexType, date: date) + request.query { result in + switch result { + case .success(let result): + continuation.resume(returning: (result)) + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } +} diff --git a/KissMeConsole/Sources/KissConsole.swift b/KissMeConsole/Sources/KissConsole.swift index fe2502a..3af3955 100644 --- a/KissMeConsole/Sources/KissConsole.swift +++ b/KissMeConsole/Sources/KissConsole.swift @@ -60,6 +60,10 @@ class KissConsole: KissMe.ShopContext { case shorts = "shorts" case shortsAll = "shorts all" + // KRX 지수 열람 + case index = "index" + case indexAll = "index all" + // 종목 열람 case loadShop = "load shop" case updateShop = "update shop" @@ -95,7 +99,7 @@ class KissConsole: KissMe.ShopContext { return false case .investor, .investorAll: return true - case .shorts, .shortsAll: + case .shorts, .shortsAll, .index, .indexAll: return false case .loadShop, .updateShop, .look, .holiday: return false @@ -227,6 +231,9 @@ class KissConsole: KissMe.ShopContext { case .shorts: await onShorts(args) case .shortsAll: onShortsAll(args) + + case .index: await onIndex(args) + case .indexAll: onIndexAll(args) case .loadShop: await onLoadShop() case .updateShop: await onUpdateShop() @@ -839,6 +846,26 @@ extension KissConsole { } + private func onIndex(_ args: [String]) async { + let indexType: DomesticExtra.IndexType? = (args.isEmpty ? .krx: .init(rawValue: args[0])) + guard let indexType = indexType else { + print("Invalid KRX index type") + return + } + do { + // TODO: Work more +// _ = try await getIndexPrice(indexType, startDate: , endDate: ) + } catch { + print(error) + } + } + + + private func onIndexAll(_ args: [String]) { + // TODO: Work more + } + + private func onCandle(_ args: [String]) async { let productNo: String? = (args.isEmpty ? currentShortCode: args[0]) guard let productNo = productNo else { diff --git a/bin/data b/bin/data index 0db048d..8ecb2d6 160000 --- a/bin/data +++ b/bin/data @@ -1 +1 @@ -Subproject commit 0db048df7aa6c6ddda910e0ee7fb7c701a5b343d +Subproject commit 8ecb2d68fe4b0bfb2bae569bfc90638812e62beb diff --git a/projects/macos/KissMe.xcodeproj/project.pbxproj b/projects/macos/KissMe.xcodeproj/project.pbxproj index 8d27c33..d941ad4 100644 --- a/projects/macos/KissMe.xcodeproj/project.pbxproj +++ b/projects/macos/KissMe.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 3435A7F72A35D82000D604F1 /* DomesticShortSelling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3435A7F62A35D82000D604F1 /* DomesticShortSelling.swift */; }; 349C26AB2A1EAE2400F3EC91 /* KissProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349C26AA2A1EAE2400F3EC91 /* KissProfile.swift */; }; 34D3680F2A2AA0BE005E6756 /* PropertyIterable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D3680E2A2AA0BE005E6756 /* PropertyIterable.swift */; }; + 34E7B9112A49BD2800B3AB9F /* DomesticIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E7B9102A49BD2800B3AB9F /* DomesticIndex.swift */; }; 34F1900C2A41982A0068C697 /* IndexResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F1900B2A41982A0068C697 /* IndexResult.swift */; }; 34F1900F2A426D150068C697 /* ShopContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F1900E2A426D150068C697 /* ShopContext.swift */; }; 34F190112A4394EB0068C697 /* LocalContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F190102A4394EB0068C697 /* LocalContext.swift */; }; @@ -82,6 +83,7 @@ 3435A7F62A35D82000D604F1 /* DomesticShortSelling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomesticShortSelling.swift; sourceTree = ""; }; 349C26AA2A1EAE2400F3EC91 /* KissProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KissProfile.swift; sourceTree = ""; }; 34D3680E2A2AA0BE005E6756 /* PropertyIterable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyIterable.swift; sourceTree = ""; }; + 34E7B9102A49BD2800B3AB9F /* DomesticIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomesticIndex.swift; sourceTree = ""; }; 34F1900B2A41982A0068C697 /* IndexResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexResult.swift; sourceTree = ""; }; 34F1900E2A426D150068C697 /* ShopContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShopContext.swift; sourceTree = ""; }; 34F190102A4394EB0068C697 /* LocalContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalContext.swift; sourceTree = ""; }; @@ -164,6 +166,7 @@ 341F5EE62A0F3EFB00962D48 /* Domestic */ = { isa = PBXGroup; children = ( + 34E7B90F2A4994AF00B3AB9F /* KRX300 */, 3435A7F52A35D68000D604F1 /* ShortSelling */, 341F5F122A16CD3C00962D48 /* Shop */, 341F5EE42A0F3EF400962D48 /* DomesticStock.swift */, @@ -218,6 +221,14 @@ path = ShortSelling; sourceTree = ""; }; + 34E7B90F2A4994AF00B3AB9F /* KRX300 */ = { + isa = PBXGroup; + children = ( + 34E7B9102A49BD2800B3AB9F /* DomesticIndex.swift */, + ); + path = KRX300; + sourceTree = ""; + }; 34F1900A2A41981A0068C697 /* Index */ = { isa = PBXGroup; children = ( @@ -372,6 +383,7 @@ 341F5EF92A0F907300962D48 /* DomesticStockPriceResult.swift in Sources */, 341F5EE12A0F373B00962D48 /* Login.swift in Sources */, 341F5EF52A0F891200962D48 /* KissAccount.swift in Sources */, + 34E7B9112A49BD2800B3AB9F /* DomesticIndex.swift in Sources */, 341F5F0D2A15222E00962D48 /* AuthRequest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0;