Files
KissMe/KissMeGolder/Sources/KissSimulator.swift
2023-07-04 22:53:54 +09:00

155 lines
4.5 KiB
Swift

//
// 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)
}
}