Working on simulator

This commit is contained in:
2023-07-04 22:53:54 +09:00
parent a0cca774d4
commit 99ad984f92
6 changed files with 175 additions and 5 deletions

View File

@@ -44,11 +44,15 @@ public struct KissIndexResult: Codable {
public struct KissMatrixResult: Codable {
public let code: Int
public let kmis: [String]
public let day: String
public let time: String
public let output: [KissIndexResult.Output]
public init(code: Int, kmis: [String], output: [KissIndexResult.Output]) {
public init(code: Int, kmis: [String], day: String, time: String, output: [KissIndexResult.Output]) {
self.code = code
self.kmis = kmis
self.day = day
self.time = time
self.output = output
}
}

View File

@@ -0,0 +1,154 @@
//
// KissSimulator.swift
// KissMeGolder
//
// Created by ened-book-m1 on 2023/06/30.
//
import Foundation
import KissMe
struct Stock: Codable {
let productNo: String
let quantity: Int
let averagePrice: Int
}
class Balance: Codable {
var cash: Int
var stocks: [Stock]
init() {
cash = 10_000_000
stocks = []
}
}
class KissSimulator: ShopContext {
let balance: Balance
private var dataPath: URL
private let candleCache = CandleCache()
override init() {
balance = Balance()
dataPath = URL.currentDirectory().appending(path: "data")
super.init()
loadShop(url: dataPath.appending(path: "shop-products.csv"))
}
init(balanceJson: URL) {
do {
let data = try Data(contentsOf: balanceJson, options: .uncached)
let balance = try JSONDecoder().decode(Balance.self, from: data)
self.balance = balance
} catch {
printError(error)
self.balance = Balance()
}
dataPath = URL.currentDirectory().appending(path: "data")
}
func simulate(_ result: KissMatrixResult) {
// , .
// 30 ,
// 30 , ( ) , 30
// weight 1-2 ?
// weight 1-2 ?
let topCount = min(result.output.count / 2, 30)
let topResult = result.output.prefix(topCount)
let bottomCount = min(result.output.count - topCount, 20)
let bottomResult = result.output.suffix(bottomCount)
///
for item in topResult {
guard let price = candleCache.getPrice(productNo: item.shortCode, day: result.day, time: result.time) else {
continue
}
}
///
for item in bottomResult {
}
}
func simulate(logAt: String, startDate: Date, endDate: Date, interval: TimeInterval = 10 * 60) {
var curDate = startDate
while curDate <= endDate {
guard let result = loadLog(logAt: logAt, day: curDate.yyyyMMdd, time: curDate.HHmmss) else {
printError("Cannot load log at \(curDate.yyyyMMdd_HHmmss_forTime)")
break
}
simulate(result)
curDate.addTimeInterval(interval)
}
}
}
extension KissSimulator {
private func loadLog(logAt: String, day: String, time: String) -> KissMatrixResult? {
let subPath = "\(logAt)/\(day)_\(time)_0000.log"
let logUrl = URL.currentDirectory().appending(path: subPath)
do {
let data = try Data(contentsOf: logUrl, options: .uncached)
let result = try JSONDecoder().decode(KissMatrixResult.self, from: data)
return result
} catch {
printError(error)
return nil
}
}
}
public class CandleCache {
private var candleCaches: [String: [Domestic.Candle]] = [:]
func getCandle(productNo: String, day: String, time: String) -> Domestic.Candle? {
let basePath = URL.currentDirectory().appending(path: "data")
let candleUrl = basePath.appending(path: "\(productNo)/min/candle-\(day).log")
let candles: [Domestic.Candle]
if let cache = candleCaches[candleUrl.path] {
candles = cache
}
else {
do {
candles = try [Domestic.Candle].readCsv(fromFile: candleUrl)
candleCaches[candleUrl.path] = candles
} catch {
printError(error)
return nil
}
}
guard let candle = candles.first(where: { $0.stockConclusionTime == time }) else {
return nil
}
return candle
}
func getPrice(productNo: String, day: String, time: String) -> Int? {
guard let candle = getCandle(productNo: productNo, day: day, time: time) else {
return nil
}
return Int(candle.currentStockPrice)
}
}

View File

@@ -7,4 +7,12 @@
import Foundation
#if true
KissGolder().run()
#else
let startDate = "20230626 090000".modelDate!
let endDate = "20230630 153000".modelDate!
KissSimulator().simulate(logAt: "data", startDate: startDate, endDate: endDate)
#endif

View File

@@ -85,7 +85,7 @@ class KissMatrix {
return taskResult
}
mergeResult(results)
mergeResult(results, date: runDate)
semaphore.signal()
}
@@ -144,7 +144,7 @@ class KissMatrix {
}
private func mergeResult(_ results: [KissIndexResult]) {
private func mergeResult(_ results: [KissIndexResult], date: Date) {
let indexCount = results.count
var mergedOutput = [String: [KissIndexResult.Output]]()
for result in results {
@@ -168,7 +168,7 @@ class KissMatrix {
let kmis = results.map { $0.kmi }
let matrixResult = KissMatrixResult(code: 200, kmis: kmis, output: normalized)
let matrixResult = KissMatrixResult(code: 200, kmis: kmis, day: date.yyyyMMdd, time: date.HHmmss, output: normalized)
do {
let jsonData = try JSONEncoder().encode(matrixResult)
try FileHandle.standardOutput.write(contentsOf: jsonData)

View File

@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
340A4DCC2A4E4C37005A1FBA /* KissGolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340A4DCB2A4E4C37005A1FBA /* KissGolder.swift */; };
340A4DD22A4EBEB0005A1FBA /* KissSimulator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340A4DD12A4EBEB0005A1FBA /* KissSimulator.swift */; };
3498435C2A24DC1300E85B08 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3498435B2A24DC1300E85B08 /* main.swift */; };
349843642A24DC7800E85B08 /* KissMe.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 349843632A24DC7800E85B08 /* KissMe.framework */; };
349843652A24DC7800E85B08 /* KissMe.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 349843632A24DC7800E85B08 /* KissMe.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -38,6 +39,7 @@
/* Begin PBXFileReference section */
340A4DCB2A4E4C37005A1FBA /* KissGolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KissGolder.swift; sourceTree = "<group>"; };
340A4DD12A4EBEB0005A1FBA /* KissSimulator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KissSimulator.swift; sourceTree = "<group>"; };
349843582A24DC1300E85B08 /* KissMeGolder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KissMeGolder; sourceTree = BUILT_PRODUCTS_DIR; };
3498435B2A24DC1300E85B08 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
349843632A24DC7800E85B08 /* KissMe.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = KissMe.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -77,6 +79,7 @@
children = (
3498435B2A24DC1300E85B08 /* main.swift */,
340A4DCB2A4E4C37005A1FBA /* KissGolder.swift */,
340A4DD12A4EBEB0005A1FBA /* KissSimulator.swift */,
);
name = KissMeGolder;
path = ../../KissMeGolder/Sources;
@@ -150,6 +153,7 @@
buildActionMask = 2147483647;
files = (
340A4DCC2A4E4C37005A1FBA /* KissGolder.swift in Sources */,
340A4DD22A4EBEB0005A1FBA /* KissSimulator.swift in Sources */,
3498435C2A24DC1300E85B08 /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;