Split investor.csv by monthly data

This commit is contained in:
2023-06-23 00:32:02 +09:00
parent bb48abd3d3
commit 995b79810d
10 changed files with 146 additions and 14 deletions

View File

@@ -21,6 +21,9 @@ let PreferredShortsTPS: UInt64 = 5
/// Limit to request a top query
let PreferredTopTPS: UInt64 = 5
/// Limit to request a investor query
let PreferredInvestorTPS: UInt64 = 19
/// How many seconds does 1 day have?
let SecondsForOneDay: TimeInterval = 60 * 60 * 24

View File

@@ -13,18 +13,39 @@ extension KissConsole {
func getInvestor(productNo: String) async throws -> Bool {
let result = try await account!.getInvestorVolume(productNo: productNo)
if let output = result.output {
print(output.count)
print("Total output: \(output.count) productNo: \(productNo)")
guard let recentDay = output.first?.stockBusinessDate else {
print("No investor items")
return false
var months = [String: [InvestorVolumeResult.OutputDetail]]()
for item in output {
let yyyyMM = String(item.stockBusinessDate.prefix(6))
if let _ = months[yyyyMM] {
months[yyyyMM]!.append(item)
}
else {
months[yyyyMM] = [item]
}
}
let fileUrl = KissConsole.investorFileUrl(productNo: productNo, day: recentDay)
try output.writeCsv(toFile: fileUrl, localized: localized)
try await Task.sleep(nanoseconds: 1_000_000_000 / PreferredCandleTPS)
for (month, items) in months {
let descItems = items.sorted(by: { $0.stockBusinessDate > $1.stockBusinessDate })
guard descItems.count > 0 else {
continue
}
let fileUrl = KissConsole.investorFileUrl(productNo: productNo, day: month+"01")
try descItems.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 / PreferredInvestorTPS)
return true
}
}

View File

@@ -111,6 +111,7 @@ extension KissConsole {
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))

View File

@@ -252,3 +252,63 @@ private func update_candle_csv_header_field() {
print(error)
}
}
private func split_investor_csv() {
guard let enumerator = FileManager.subPathFiles("data") else {
return
}
var urls = [URL]()
for case let fileUrl as URL in enumerator {
guard fileUrl.pathExtension == "csv" else {
continue
}
if fileUrl.lastPathComponent.prefix(9) == "investor-" {
urls.append(fileUrl)
}
}
do {
for url in urls {
let investorDir = url.deletingLastPathComponent()
let productNoDir = investorDir.deletingLastPathComponent()
let productNo = productNoDir.lastPathComponent
let output = try [InvestorVolumeResult.OutputDetail].readCsv(fromFile: url, verifyHeader: true)
var months = [String: [InvestorVolumeResult.OutputDetail]]()
for item in output {
let yyyyMM = String(item.stockBusinessDate.prefix(6))
if let _ = months[yyyyMM] {
months[yyyyMM]!.append(item)
}
else {
months[yyyyMM] = [item]
}
}
for (month, items) in months {
let descItems = items.sorted(by: { $0.stockBusinessDate > $1.stockBusinessDate })
guard descItems.count > 0 else {
continue
}
let fileUrl = KissConsole.investorFileUrl(productNo: productNo, day: month+"01")
try descItems.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: false)
}
try FileManager.default.removeItem(at: url)
}
} catch {
print(error)
}
}

View File

@@ -26,7 +26,7 @@ extension KissIndex {
}
return false
}
print(shorts.count)
//print(shorts.count)
let prices = try await collectPrices(date: date) { price in
if let quantity = Int(price.lastShortSellingConclusionQuantity), quantity > 0 {
@@ -36,10 +36,10 @@ extension KissIndex {
}
return false
}
print(prices.count)
//print(prices.count)
} catch {
print(error)
//print(error)
writeError(error, kmi: kmi)
}

View File

@@ -11,6 +11,27 @@ import Foundation
extension KissIndex {
func indexSet_0004(date: Date, config: String?, kmi: KissIndexType) {
if productsCount == 0 {
loadShop(url: KissIndex.shopProductsUrl)
}
let semaphore = DispatchSemaphore(value: 0)
Task {
var scoreMap = [String: Double]()
// TODO: work
semaphore.signal()
}
semaphore.wait()
}
private func pickNearInvestorUrl(productNo: String, date: Date) {
let subPath = "data/\(productNo)/investor"
let subFile = "investor-\(date.yyyyMM01).csv"
let fileUrl = URL.currentDirectory().appending(path: subFile)
// TODO: work
}
}

View File

@@ -98,7 +98,7 @@ class KissIndex: KissMe.ShopContext {
extension KissIndex {
func collectShorts(date: Date, filter: @escaping (DomesticExtra.Shorts) -> Bool) async throws -> [DomesticExtra.Shorts] {
let shorts = try await withThrowingTaskGroup(of: DomesticExtra.Shorts?.self, returning: [DomesticExtra.Shorts].self) { taskGroup in
let all = getAllProducts()
@@ -110,7 +110,7 @@ extension KissIndex {
let shorts = try [DomesticExtra.Shorts].readCsv(fromFile: shortsUrl)
let targetShorts = shorts.filter { $0.stockBusinessDate == yyyyMMdd }
if let aShorts = targetShorts.first, filter(aShorts) {
return aShorts
}
@@ -155,6 +155,10 @@ extension KissIndex {
}
return prices
}
}
extension KissIndex {
static var shopProductsUrl: URL {
URL.currentDirectory().appending(path: "data/shop-products.csv")
@@ -182,6 +186,7 @@ extension KissIndex {
extension KissIndex {
func normalizeAndWrite(scoreMap: [String: Double], includeName: Bool = false, kmi: KissIndexType) {
let totalScores = scoreMap.reduce(0, { $0 + $1.value })
let scoreArray = scoreMap.map { ($0.key, $0.value) }.sorted(by: { $0.1 > $1.1 })

View File

@@ -6,6 +6,9 @@ PER 의 적정값에 해당되는 종목을 선별합니다.
**한국투자증권**에서 우선적으로 제공되는 PER 를 사용합니다.
* [주식현재가 시세[v1_국내주식-008]](https://apiportal.koreainvestment.com/apiservice/apiservice-domestic-stock-quotations#L_07802512-4f49-4486-91b4-1050b6f5dc9d)
* /uapi/domestic-stock/v1/quotations/inquire-price
차후에는 PER 값을 예측하도록 개선될 예정입니다.
적합한 PER 를 선별하는 기준은 다음과 같습니다.

View File

@@ -1,2 +1,20 @@
# KMI-0004
## How to
외국인 거래량/보유량을 기준으로 종목을 선별합니다.
여기에 2가지 방식이 제안됩니다.
* 3일 연속매수하여 계속 증가했는지 검사.
* 4일전보다 보유량이 증가했는지 검사.
### 3일 연속매수
### 4일이후 보유량 상승
## Usage
## Configuration