Show current stock balance
This commit is contained in:
@@ -148,7 +148,7 @@ public struct Domestic {
|
||||
/// 국내주식주문 - 주식잔고조회[v1_국내주식-006]
|
||||
///
|
||||
public struct StockBalanceRequest: OrderRequest {
|
||||
public typealias KResult = String
|
||||
public typealias KResult = BalanceResult
|
||||
|
||||
public var url: String {
|
||||
"/uapi/domestic-stock/v1/trading/inquire-balance"
|
||||
@@ -161,6 +161,7 @@ public struct Domestic {
|
||||
"appkey": credential.appKey,
|
||||
"appsecret": credential.appSecret,
|
||||
"tr_id": trId,
|
||||
"tr_cont": isNext ? "N": " ",
|
||||
]
|
||||
}
|
||||
public var body: [String: Any] {
|
||||
@@ -184,18 +185,20 @@ public struct Domestic {
|
||||
|
||||
private var trId: String {
|
||||
if credential.isMock {
|
||||
return "VTTC0803U"
|
||||
return "VTTC8434R"
|
||||
}
|
||||
else {
|
||||
return "TTTC0803U"
|
||||
return "TTTC8434R"
|
||||
}
|
||||
}
|
||||
|
||||
public let accessToken: String
|
||||
let isNext: Bool
|
||||
|
||||
public init(credential: Credential, accessToken: String) {
|
||||
public init(credential: Credential, accessToken: String, isNext: Bool) {
|
||||
self.credential = credential
|
||||
self.accessToken = accessToken
|
||||
self.isNext = isNext
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +206,7 @@ public struct Domestic {
|
||||
/// 국내주식주문 - 매수가능조회[v1_국내주식-007]
|
||||
///
|
||||
public struct StockPossibleOrderRequest: OrderRequest {
|
||||
public typealias KResult = OrderPossibleResult
|
||||
public typealias KResult = PossibleOrderResult
|
||||
|
||||
public var url: String {
|
||||
"/uapi/domestic-stock/v1/trading/inquire-psbl-order"
|
||||
@@ -216,6 +219,7 @@ public struct Domestic {
|
||||
"appkey": credential.appKey,
|
||||
"appsecret": credential.appSecret,
|
||||
"tr_id": trId,
|
||||
"tr_cont": isNext ? "N": " ",
|
||||
]
|
||||
}
|
||||
public var body: [String: Any] {
|
||||
@@ -247,13 +251,15 @@ public struct Domestic {
|
||||
|
||||
let orderDivision: OrderDivision
|
||||
let orderPrice: Int
|
||||
let isNext: Bool
|
||||
|
||||
public init(credential: Credential, accessToken: String, productNo: String, orderDivision: OrderDivision, orderPrice: Int) {
|
||||
public init(credential: Credential, accessToken: String, productNo: String, orderDivision: OrderDivision, orderPrice: Int, isNext: Bool) {
|
||||
self.credential = credential
|
||||
self.accessToken = accessToken
|
||||
self.productNo = productNo
|
||||
self.orderDivision = orderDivision
|
||||
self.orderPrice = orderPrice
|
||||
self.isNext = isNext
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,7 +332,7 @@ extension KissAccount {
|
||||
}
|
||||
|
||||
|
||||
public func getStockBalance() async throws -> Bool {
|
||||
public func getStockBalance() async throws -> BalanceResult {
|
||||
return try await withUnsafeThrowingContinuation { continuation in
|
||||
|
||||
guard let accessToken = accessToken else {
|
||||
@@ -334,12 +340,20 @@ extension KissAccount {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: work
|
||||
let request = Domestic.StockBalanceRequest(credential: credential, accessToken: accessToken, isNext: false)
|
||||
request.query { result in
|
||||
switch result {
|
||||
case .success(let result):
|
||||
continuation.resume(returning: result)
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func canOrderStock() async throws -> Bool {
|
||||
public func canOrderStock(productNo: String, division: OrderDivision, price: Int) async throws -> PossibleOrderResult {
|
||||
return try await withUnsafeThrowingContinuation { continuation in
|
||||
|
||||
guard let accessToken = accessToken else {
|
||||
@@ -347,7 +361,15 @@ extension KissAccount {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: work
|
||||
let request = Domestic.StockPossibleOrderRequest(credential: credential, accessToken: accessToken, productNo: productNo, orderDivision: division, orderPrice: price, isNext: false)
|
||||
request.query { result in
|
||||
switch result {
|
||||
case .success(let result):
|
||||
continuation.resume(returning: result)
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import Foundation
|
||||
|
||||
|
||||
public enum YesNo: String, Codable {
|
||||
case none = ""
|
||||
case yes = "Y"
|
||||
case no = "N"
|
||||
}
|
||||
|
||||
@@ -68,7 +68,238 @@ public struct OrderRevisionResult: Codable {
|
||||
}
|
||||
|
||||
|
||||
public struct OrderPossibleResult: Codable {
|
||||
public struct BalanceResult: Codable {
|
||||
public let resultCode: String
|
||||
public let messageCode: String
|
||||
public let message: String
|
||||
public let straightInqueryCondition: String?
|
||||
public let straightInqueryKey: String?
|
||||
public let output1: [OutputDetail1]?
|
||||
public let output2: [OutputDetail2]?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case resultCode = "rt_cd"
|
||||
case messageCode = "msg_cd"
|
||||
case message = "msg1"
|
||||
case straightInqueryCondition = "ctx_area_fk100"
|
||||
case straightInqueryKey = "ctx_area_nk100"
|
||||
case output1 = "output1"
|
||||
case output2 = "output2"
|
||||
}
|
||||
|
||||
public struct OutputDetail1: Codable {
|
||||
/// 상품번호
|
||||
public let productNo: String
|
||||
|
||||
/// 상품명
|
||||
public let productName: String
|
||||
|
||||
/// 매매구분명 (매수매도구분)
|
||||
public let tradeDivisionCode: String
|
||||
|
||||
/// 전일매수수량
|
||||
public let previousDayBuyQuantity: String
|
||||
|
||||
/// 전일매도수량
|
||||
public let previousDaySellQuantity: String
|
||||
|
||||
/// 금일매수수량
|
||||
public let todayBuyQuantity: String
|
||||
|
||||
/// 금일매도수량
|
||||
public let todaySellQuantity: String
|
||||
|
||||
/// 보유수량
|
||||
public let holdingQuantity: String
|
||||
|
||||
/// 주문가능수량
|
||||
public let orderPossibleQuantity: String
|
||||
|
||||
/// 매입평균가격 (매입금액 / 보유수량)
|
||||
public let averagePurchasePrice: String
|
||||
|
||||
/// 매입금액
|
||||
public let purchaseAmount: String
|
||||
|
||||
/// 현재가
|
||||
public let currentPrice: String
|
||||
|
||||
/// 평가금액
|
||||
public let evaluationAmount: String
|
||||
|
||||
/// 평가손익금액 (평가금액 - 매입금액)
|
||||
public let evaluationProfitLossAmount: String
|
||||
|
||||
/// 평가손익율
|
||||
public let evaluationProfitLossRate: String
|
||||
|
||||
/// 평가수익율
|
||||
public let evaluationEarningRate: String
|
||||
|
||||
/// 대출일자
|
||||
public let loanDate: String
|
||||
|
||||
/// 대출금액
|
||||
public let loanAmount: String
|
||||
|
||||
/// 대주매각대금
|
||||
public let shortSellingAmount: String
|
||||
|
||||
/// 만기일자
|
||||
public let expiredDate: String
|
||||
|
||||
/// 등락율
|
||||
public let fluctuationRate: String
|
||||
|
||||
/// 전일대비증감
|
||||
public let netChangeFluctuation: String
|
||||
|
||||
/// 종목증거금율명
|
||||
public let marginRequirementRatioName: String
|
||||
|
||||
/// 보증금율명
|
||||
public let depositRateName: String
|
||||
|
||||
/// 대용가격
|
||||
public let substitutePrice: String
|
||||
|
||||
/// 주식대출단가
|
||||
public let stockLoanPrice: String
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case productNo = "pdno"
|
||||
case productName = "prdt_name"
|
||||
case tradeDivisionCode = "trad_dvsn_name"
|
||||
case previousDayBuyQuantity = "bfdy_buy_qty"
|
||||
case previousDaySellQuantity = "bfdy_sll_qty"
|
||||
case todayBuyQuantity = "thdt_buyqty"
|
||||
case todaySellQuantity = "thdt_sll_qty"
|
||||
case holdingQuantity = "hldg_qty"
|
||||
case orderPossibleQuantity = "ord_psbl_qty"
|
||||
case averagePurchasePrice = "pchs_avg_pric"
|
||||
case purchaseAmount = "pchs_amt"
|
||||
case currentPrice = "prpr"
|
||||
case evaluationAmount = "evlu_amt"
|
||||
case evaluationProfitLossAmount = "evlu_pfls_amt"
|
||||
case evaluationProfitLossRate = "evlu_pfls_rt"
|
||||
case evaluationEarningRate = "evlu_erng_rt"
|
||||
case loanDate = "loan_dt"
|
||||
case loanAmount = "loan_amt"
|
||||
case shortSellingAmount = "stln_slng_chgs"
|
||||
case expiredDate = "expd_dt"
|
||||
case fluctuationRate = "fltt_rt"
|
||||
case netChangeFluctuation = "bfdy_cprs_icdc"
|
||||
case marginRequirementRatioName = "item_mgna_rt_name"
|
||||
case depositRateName = "grta_rt_name"
|
||||
case substitutePrice = "sbst_pric"
|
||||
case stockLoanPrice = "stck_loan_unpr"
|
||||
}
|
||||
}
|
||||
|
||||
public struct OutputDetail2: Codable {
|
||||
/// 예수금총금액 (예수금)
|
||||
public let depositTotalAmount: String
|
||||
|
||||
/// 익일정산금액 (D+1 예수금)
|
||||
public let nextDayCalcAmount: String
|
||||
|
||||
/// 가수도정산금액 (D+2 예수금)
|
||||
public let nextTwoDayCalcAmount: String
|
||||
|
||||
/// CMA평가금액
|
||||
public let cmaEvaluationAmount: String
|
||||
|
||||
/// 전일매수금액
|
||||
public let previousDayBuyAmount: String
|
||||
|
||||
/// 금일매수금액
|
||||
public let todayBuyAmount: String
|
||||
|
||||
/// 익일자동상환금액
|
||||
public let nextDayAutoRedemptionAmount: String
|
||||
|
||||
/// 전일매도금액
|
||||
public let previousDaySellAmount: String
|
||||
|
||||
/// 금일매도금액
|
||||
public let todaySellAmount: String
|
||||
|
||||
/// D+2자동상환금액
|
||||
public let nextTwoDayAutoRedemptionAmount: String
|
||||
|
||||
/// 전일제비용금액
|
||||
public let previousDayExpensesAmount: String
|
||||
|
||||
/// 금일제비용금액
|
||||
public let todayExpensesAmount: String
|
||||
|
||||
/// 총대출금액
|
||||
public let totalLoanAmount: String
|
||||
|
||||
/// 유가평가금액
|
||||
public let securitiesEvaluationAmount: String
|
||||
|
||||
/// 총평가금액
|
||||
public let totalEvaluationAmount: String
|
||||
|
||||
/// 순자산금액
|
||||
public let netAssetAmount: String
|
||||
|
||||
/// 융자금자동상환여부
|
||||
public let loanAutoRedemptionAllowable: YesNo
|
||||
|
||||
/// 매입금액합계금액
|
||||
public let purchaseAmountSum: String
|
||||
|
||||
/// 평가금액합계금액
|
||||
public let evaluationAmountSum: String
|
||||
|
||||
/// 평가손익합계금액
|
||||
public let evaluationProfitLossAmountSum: String
|
||||
|
||||
/// 총대주매각대금
|
||||
public let shortSellingAmountSum: String
|
||||
|
||||
/// 전일총자산평가금액
|
||||
public let previousDayAssetEvalutionSum: String
|
||||
|
||||
/// 자산증감액
|
||||
public let assetFluctuationAmount: String
|
||||
|
||||
/// 자산증감수익율
|
||||
public let assetFluctuationRate: String
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case depositTotalAmount = "dnca_tot_amt"
|
||||
case nextDayCalcAmount = "nxdy_excc_amt"
|
||||
case nextTwoDayCalcAmount = "prvs_rcdl_excc_amt"
|
||||
case cmaEvaluationAmount = "cma_evlu_amt"
|
||||
case previousDayBuyAmount = "bfdy_buy_amt"
|
||||
case todayBuyAmount = "thdt_buy_amt"
|
||||
case nextDayAutoRedemptionAmount = "nxdy_auto_rdpt_amt"
|
||||
case previousDaySellAmount = "bfdy_sll_amt"
|
||||
case todaySellAmount = "thdt_sll_amt"
|
||||
case nextTwoDayAutoRedemptionAmount = "d2_auto_rdpt_amt"
|
||||
case previousDayExpensesAmount = "bfdy_tlex_amt"
|
||||
case todayExpensesAmount = "thdt_tlex_amt"
|
||||
case totalLoanAmount = "tot_loan_amt"
|
||||
case securitiesEvaluationAmount = "scts_evlu_amt"
|
||||
case totalEvaluationAmount = "tot_evlu_amt"
|
||||
case netAssetAmount = "nass_amt"
|
||||
case loanAutoRedemptionAllowable = "fncg_gld_auto_rdpt_yn"
|
||||
case purchaseAmountSum = "pchs_amt_smtl_amt"
|
||||
case evaluationAmountSum = "evlu_amt_smtl_amt"
|
||||
case evaluationProfitLossAmountSum = "evlu_pfls_smtl_amt"
|
||||
case shortSellingAmountSum = "tot_stln_slng_chgs"
|
||||
case previousDayAssetEvalutionSum = "bfdy_tot_asst_evlu_amt"
|
||||
case assetFluctuationAmount = "asst_icdc_amt"
|
||||
case assetFluctuationRate = "asst_icdc_erng_rt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct PossibleOrderResult: Codable {
|
||||
public let resultCode: String
|
||||
public let messageCode: String
|
||||
public let message: String
|
||||
|
||||
@@ -19,6 +19,7 @@ extension DomesticShop {
|
||||
}
|
||||
|
||||
/// 한국예탁결제원_주식정보서비스 - 시장구분을 기준으로 단축종목번호와 종목명 조회
|
||||
///
|
||||
public struct Product10Request: SeibroRequest {
|
||||
public typealias KResult = String
|
||||
|
||||
|
||||
@@ -53,14 +53,14 @@ class KissConsole {
|
||||
return false
|
||||
case .logout, .top, .buy, .sell, .cancel:
|
||||
return true
|
||||
case .openBag:
|
||||
return true
|
||||
case .loadShop, .updateShop, .look:
|
||||
return false
|
||||
case .showcase:
|
||||
return false
|
||||
case .loves, .love, .hate:
|
||||
return false
|
||||
case .openBag:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,12 +119,21 @@ class KissConsole {
|
||||
case .loginReal: await onLogin(isMock: false)
|
||||
case .logout: await onLogout()
|
||||
case .top: await onTop(args)
|
||||
|
||||
case .buy: await onBuy(args)
|
||||
case .sell: await onSell(args)
|
||||
case .cancel: await onCancel(args)
|
||||
case .openBag: await onOpenBag()
|
||||
|
||||
case .loadShop: await onLoadShop()
|
||||
case .updateShop: await onUpdateShop()
|
||||
case .look: await onLook(args)
|
||||
|
||||
case .showcase: await onShowcase()
|
||||
case .loves: await onLoves()
|
||||
case .love: await onLove(args)
|
||||
case .hate: await onHate(args)
|
||||
|
||||
default:
|
||||
print("Unknown command: \(line)")
|
||||
}
|
||||
@@ -323,6 +332,25 @@ extension KissConsole {
|
||||
}
|
||||
|
||||
|
||||
private func onOpenBag() async {
|
||||
do {
|
||||
let result = try await account!.getStockBalance()
|
||||
if let output = result.output1 {
|
||||
for item in output {
|
||||
print("\(item)")
|
||||
}
|
||||
}
|
||||
if let output = result.output2 {
|
||||
for item in output {
|
||||
print("\(item)")
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
print("\(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func onLoadShop() async {
|
||||
return await withUnsafeContinuation { continuation in
|
||||
self.loadShop()
|
||||
@@ -410,6 +438,26 @@ extension KissConsole {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func onShowcase() async {
|
||||
// TODO: write
|
||||
}
|
||||
|
||||
|
||||
private func onLoves() async {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private func onLove(_ args: [String]) async {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private func onHate(_ args: [String]) async {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ command | 설명
|
||||
WIP `buy (ISCD) (수량)` | 구매
|
||||
WIP `sell (ISCD) (수량)` | 판매
|
||||
WIP `cancel (ISCD)` | 주문 취소
|
||||
WIP `open bag` | 보유 종목 열람
|
||||
`open bag` | 보유 종목 열람
|
||||
`load shop` | data/shop-products.csv 로부터 전체 상품을 로딩
|
||||
`update shop` | 금융위원회_KRX상장종목정보 로부터 전체 상품을 얻어서 data/shop-products.csv 로 저장
|
||||
`look (상품명)` | (상품명) 에 해당되는 ISCD 를 표시함
|
||||
|
||||
Reference in New Issue
Block a user