154 lines
6.4 KiB
Swift
154 lines
6.4 KiB
Swift
//
|
|
// KissConsole+Price.swift
|
|
// KissMeConsole
|
|
//
|
|
// Created by ened-book-m1 on 2023/06/11.
|
|
//
|
|
|
|
import Foundation
|
|
import KissMe
|
|
|
|
|
|
extension KissConsole {
|
|
|
|
func getCurrentPrice(productNo: String, printConsole: Bool = false) async -> Bool {
|
|
do {
|
|
let result = try await account!.getCurrentPrice(productNo: productNo)
|
|
guard let output = result.output else {
|
|
print("Invalid result's output for \(productNo)")
|
|
return false
|
|
}
|
|
|
|
if printConsole {
|
|
printCurrentPrice(output)
|
|
}
|
|
|
|
let price = CapturePrice(captureTime: Date(), price: output)
|
|
let yyyyMM = String(price.stockBusinessDate.prefix(6))
|
|
|
|
let fileUrl = KissConsole.priceFileUrl(productNo: productNo, day: yyyyMM+"01")
|
|
try [price].mergeCsv(toFile: fileUrl, merging: { this, file in
|
|
var merged = this
|
|
for old in file {
|
|
if nil == this.first(where: { $0.stockDateTime == old.stockDateTime }) {
|
|
merged.append(old)
|
|
}
|
|
}
|
|
merged.sort(by: { $0.stockDateTime > $1.stockDateTime })
|
|
return merged
|
|
}, localized: false)
|
|
|
|
try await Task.sleep(nanoseconds: 1_000_000_000 / PreferredNowTPS)
|
|
} catch {
|
|
print(error)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
private func printCurrentPrice(_ output: Domestic.CurrentPrice) {
|
|
let productName = getProduct(shortCode: output.shortProductCode)?.itemName ?? ""
|
|
print("\t종목명: ", productName)
|
|
print("\t업종명: ", output.koreanMarketName, output.koreanBusinessTypeName ?? "")
|
|
print("\t주식 현재가: ", output.currentStockPrice)
|
|
print("\t전일 대비: ", output.previousDayVariableRatio)
|
|
print("\t누적 거래 대금: ", output.accumulatedTradingAmount)
|
|
print("\t누적 거래량: ", output.accumulatedVolume)
|
|
print("\t전일 대비 거래량 비율: ", output.previousDayDiffVolumeRatio)
|
|
print("\t주식 시가: ", output.stockOpenningPrice)
|
|
print("\t주식 최고가: ", output.highestStockPrice)
|
|
print("\t주식 최저가: ", output.lowestStockPrice)
|
|
print("\t외국인 순매수 수량: ", output.foreignNetBuyingQuantity)
|
|
print("\t외국인 보유 수량: ", output.foreignHoldQuantity)
|
|
print("\t최종 공매도 체결 수량: ", output.lastShortSellingConclusionQuantity)
|
|
print("\t프로그램매매 순매수 수량: ", output.programTradeNetBuyingQuantity)
|
|
print("\t자본금: ", output.capital)
|
|
print("\t상장 주수: ", output.listedStockCount)
|
|
print("\tHTS 시가총액: ", output.htsTotalMarketValue)
|
|
print("\tPER: ", output.per)
|
|
print("\tPBR: ", output.pbr)
|
|
print("\t주식 단축 종목코드", output.shortProductCode)
|
|
}
|
|
|
|
func getShortsLastDate(productNo: String) -> Date? {
|
|
let startDate = Date().addingTimeInterval(-365 * SecondsForOneDay)
|
|
var backDate = Date()
|
|
|
|
/// -29일씩 이전으로 돌아가면서, 마지막으로 csv 로 저장했던 날짜를 찾는다.
|
|
while startDate < backDate {
|
|
let day = backDate.yyyyMM01
|
|
let fileUrl = KissConsole.shortsFileUrl(productNo: productNo, day: day)
|
|
guard fileUrl.isFileExists == true else {
|
|
backDate = backDate.addingTimeInterval(-29 * SecondsForOneDay)
|
|
continue
|
|
}
|
|
guard let shorts = try? [DomesticExtra.Shorts].readCsv(fromFile: fileUrl) else {
|
|
return Date.date(yyyyMMdd: day, HHmmss: "000000")
|
|
}
|
|
guard let (yyyy, mm, dd) = shorts.first?.stockBusinessDate.yyyyMMdd else {
|
|
return Date.date(yyyyMMdd: day, HHmmss: "000000")
|
|
}
|
|
guard let newDate = backDate.changing(year: yyyy, month: mm, day: dd) else {
|
|
return Date.date(yyyyMMdd: day, HHmmss: "000000")
|
|
}
|
|
return newDate.addingTimeInterval(SecondsForOneDay)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getShorts(productNo: String, startAt: Date?) async throws -> Bool {
|
|
guard let product = getProduct(shortCode: productNo) else {
|
|
print("Invalid product \(productNo)")
|
|
return false
|
|
}
|
|
|
|
let endDate = Date()
|
|
let startDate: Date
|
|
if let startAt = startAt {
|
|
startDate = startAt
|
|
}
|
|
else {
|
|
startDate = endDate.addingTimeInterval(-365 * SecondsForOneDay)
|
|
}
|
|
print("Getting \(product.isinCode), \(startDate.yyyyMMdd) ~ \(endDate.yyyyMMdd)")
|
|
|
|
let result = try await KissAccount.getShortSellingBalance(isinCode: product.isinCode, startDate: startDate, endDate: endDate)
|
|
|
|
if let outBlock = result.outBlock {
|
|
print("Total block: \(outBlock.count) productNo: \(productNo)")
|
|
|
|
var monthBlock = [String: [DomesticExtra.Shorts]]()
|
|
for block in outBlock {
|
|
let yyyyMM = String(block.stockBusinessDate.prefix(6))
|
|
if let _ = monthBlock[yyyyMM] {
|
|
monthBlock[yyyyMM]!.append(block)
|
|
}
|
|
else {
|
|
monthBlock[yyyyMM] = [block]
|
|
}
|
|
}
|
|
|
|
for (month, blocks) in monthBlock {
|
|
let descBlock = blocks.sorted(by: { $0.stockBusinessDate > $1.stockBusinessDate })
|
|
guard descBlock.count > 0 else {
|
|
continue
|
|
}
|
|
|
|
let fileUrl = KissConsole.shortsFileUrl(productNo: productNo, day: month+"01")
|
|
try descBlock.mergeCsv(toFile: fileUrl, merging: { this, file in
|
|
var merged = this
|
|
for old in file {
|
|
if nil == this.first(where: { $0.stockBusinessDate == old.stockBusinessDate }) {
|
|
merged.append(old)
|
|
}
|
|
}
|
|
merged.sort(by: { $0.stockBusinessDate > $1.stockBusinessDate })
|
|
return merged
|
|
}, localized: localized)
|
|
}
|
|
}
|
|
try await Task.sleep(nanoseconds: 1_000_000_000 / PreferredShortsTPS)
|
|
return true
|
|
}
|
|
}
|