....
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import model.AppConfig
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.javatime.datetime
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import java.io.File
|
||||
@@ -16,37 +17,110 @@ object ConfigTable : Table("app_config") {
|
||||
val vtsAccountNo = varchar("vts_account_no", 20).default("")
|
||||
val isSimulation = bool("is_simulation").default(true)
|
||||
val modelPath = varchar("model_path", 512).default("")
|
||||
val htsId = varchar("hts_id", 50).default("") // HTS ID 컬럼 추가
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
|
||||
// 2. 거래 내역 테이블 (대량 데이터용)
|
||||
// 2. 자동매매 감시 테이블
|
||||
object AutoTradeTable : Table("auto_trades") {
|
||||
val id = integer("id").autoIncrement()
|
||||
val stockCode = varchar("stock_code", 20)
|
||||
val stockName = varchar("stock_name", 100)
|
||||
val targetPrice = double("target_price") // 익절 목표가
|
||||
val stopLossPrice = double("stop_loss_price") // 손절 목표가
|
||||
val status = varchar("status", 20).default("MONITORING") // MONITORING, COMPLETED
|
||||
val isDomestic = bool("is_domestic").default(true)
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
|
||||
// 3. 거래 내역 테이블
|
||||
object TradeLogTable : Table("trade_logs") {
|
||||
val id = long("id").autoIncrement()
|
||||
val stockCode = varchar("stock_code", 20) // 종목코드
|
||||
val stockName = varchar("stock_name", 50) // 종목명
|
||||
val tradeType = varchar("trade_type", 10) // 매수/매도
|
||||
val price = double("price") // 체결가
|
||||
val quantity = integer("quantity") // 수량
|
||||
val timestamp = datetime("timestamp") // 거래 시간
|
||||
val logMessage = text("log_message") // Ollama의 판단 근거 등 상세 정보
|
||||
val stockCode = varchar("stock_code", 20)
|
||||
val stockName = varchar("stock_name", 50)
|
||||
val tradeType = varchar("trade_type", 10)
|
||||
val price = double("price")
|
||||
val quantity = integer("quantity")
|
||||
val timestamp = datetime("timestamp")
|
||||
val logMessage = text("log_message")
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
|
||||
object DatabaseFactory {
|
||||
fun init() {
|
||||
|
||||
val dbPath =File("db/autotrade_db").absolutePath
|
||||
// 드라이버를 org.h2.Driver로 설정
|
||||
val dbPath = File("db/autotrade_db").absolutePath
|
||||
Database.connect(
|
||||
"jdbc:h2:$dbPath;DB_CLOSE_DELAY=-1;",
|
||||
driver = "org.h2.Driver"
|
||||
)
|
||||
|
||||
transaction {
|
||||
SchemaUtils.create(ConfigTable, TradeLogTable)
|
||||
// 테이블 생성 (AutoTradeTable 포함)
|
||||
SchemaUtils.create(ConfigTable, TradeLogTable, AutoTradeTable)
|
||||
}
|
||||
}
|
||||
|
||||
// --- 자동매매(감시) 관련 함수 ---
|
||||
|
||||
/**
|
||||
* [추가] 종목코드로 현재 감시 중인 설정 가져오기 (웹소켓 감시용)
|
||||
*/
|
||||
fun findConfigByCode(code: String): AutoTradeItem? = transaction {
|
||||
AutoTradeTable.select {
|
||||
(AutoTradeTable.stockCode eq code) and (AutoTradeTable.status eq "MONITORING")
|
||||
}.lastOrNull()?.let {
|
||||
mapToAutoTradeItem(it)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [추가] 매수 체결 시 새로운 자동매매 감시 대상 등록
|
||||
*/
|
||||
fun saveAutoTrade(item: AutoTradeItem) {
|
||||
transaction {
|
||||
// 동일 종목이 이미 감시 중이면 삭제 후 재등록 (중복 방지)
|
||||
AutoTradeTable.deleteWhere { stockCode eq item.code }
|
||||
|
||||
AutoTradeTable.insert {
|
||||
it[stockCode] = item.code
|
||||
it[stockName] = item.name
|
||||
it[targetPrice] = item.targetPrice
|
||||
it[stopLossPrice] = item.stopLossPrice
|
||||
it[status] = "MONITORING"
|
||||
it[isDomestic] = item.isDomestic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [추가] 매도 완료 또는 취소 시 감시 대상 삭제
|
||||
*/
|
||||
fun deleteAutoTrade(code: String) {
|
||||
transaction {
|
||||
AutoTradeTable.deleteWhere { stockCode eq code }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [수정] 감시 중인 모든 종목 리스트 반환 (ActiveTradeSection UI용)
|
||||
*/
|
||||
fun getActiveAutoTrades(): List<AutoTradeItem> = transaction {
|
||||
AutoTradeTable.select { AutoTradeTable.status eq "MONITORING" }
|
||||
.map { mapToAutoTradeItem(it) }
|
||||
}
|
||||
|
||||
// ResultRow를 AutoTradeItem으로 매핑하는 내부 함수
|
||||
private fun mapToAutoTradeItem(it: ResultRow) = AutoTradeItem(
|
||||
code = it[AutoTradeTable.stockCode],
|
||||
name = it[AutoTradeTable.stockName],
|
||||
targetPrice = it[AutoTradeTable.targetPrice],
|
||||
stopLossPrice = it[AutoTradeTable.stopLossPrice],
|
||||
status = it[AutoTradeTable.status],
|
||||
isDomestic = it[AutoTradeTable.isDomestic]
|
||||
)
|
||||
|
||||
// --- 기존 설정 및 로그 관련 함수 ---
|
||||
|
||||
fun saveTradeLog(code: String, name: String, type: String, price: Double, qty: Int, msg: String) {
|
||||
transaction {
|
||||
TradeLogTable.insert {
|
||||
@@ -61,28 +135,26 @@ object DatabaseFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun findConfigByAccount(accountNo: String): AppConfig? {
|
||||
return transaction {
|
||||
ConfigTable.select {
|
||||
(ConfigTable.realAccountNo eq accountNo) or (ConfigTable.vtsAccountNo eq accountNo)
|
||||
}.lastOrNull()?.let {
|
||||
AppConfig(
|
||||
realAppKey = it[ConfigTable.realAppKey],
|
||||
realSecretKey = it[ConfigTable.realSecretKey],
|
||||
realAccountNo = it[ConfigTable.realAccountNo],
|
||||
vtsAppKey = it[ConfigTable.vtsAppKey],
|
||||
vtsSecretKey = it[ConfigTable.vtsSecretKey],
|
||||
vtsAccountNo = it[ConfigTable.vtsAccountNo],
|
||||
isSimulation = it[ConfigTable.isSimulation],
|
||||
modelPath = it[ConfigTable.modelPath]
|
||||
)
|
||||
}
|
||||
fun findConfigByAccount(accountNo: String): AppConfig? = transaction {
|
||||
ConfigTable.select {
|
||||
(ConfigTable.realAccountNo eq accountNo) or (ConfigTable.vtsAccountNo eq accountNo)
|
||||
}.lastOrNull()?.let {
|
||||
AppConfig(
|
||||
realAppKey = it[ConfigTable.realAppKey],
|
||||
realSecretKey = it[ConfigTable.realSecretKey],
|
||||
realAccountNo = it[ConfigTable.realAccountNo],
|
||||
vtsAppKey = it[ConfigTable.vtsAppKey],
|
||||
vtsSecretKey = it[ConfigTable.vtsSecretKey],
|
||||
vtsAccountNo = it[ConfigTable.vtsAccountNo],
|
||||
isSimulation = it[ConfigTable.isSimulation],
|
||||
htsId = it[ConfigTable.htsId], // htsId 로드
|
||||
modelPath = it[ConfigTable.modelPath]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun saveConfig(config: AppConfig) {
|
||||
transaction {
|
||||
// 기존 설정을 모두 지우고 최신 설정 하나만 유지
|
||||
ConfigTable.deleteAll()
|
||||
ConfigTable.insert {
|
||||
it[realAppKey] = config.realAppKey
|
||||
@@ -92,9 +164,21 @@ object DatabaseFactory {
|
||||
it[realAccountNo] = config.realAccountNo
|
||||
it[vtsAccountNo] = config.vtsAccountNo
|
||||
it[isSimulation] = config.isSimulation
|
||||
it[htsId] = config.htsId
|
||||
it[modelPath] = config.modelPath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* [수정] 감시 가격(익절/손절) 정보를 포함하도록 모델 확장
|
||||
*/
|
||||
data class AutoTradeItem(
|
||||
val code: String,
|
||||
val name: String,
|
||||
val targetPrice: Double,
|
||||
val stopLossPrice: Double, // 손절가 추가
|
||||
val status: String,
|
||||
val isDomestic: Boolean
|
||||
)
|
||||
Reference in New Issue
Block a user