This commit is contained in:
lunaticbum 2026-02-04 15:32:05 +09:00
parent 1787b72499
commit 93d8b3f0aa
2 changed files with 45 additions and 18 deletions

View File

@ -2,8 +2,9 @@ package model
import java.time.LocalDateTime
const val feesAndTaxRate = 0.3
const val minimumNetProfit = 0.8
const val feesAndTaxRate = 0.33
const val minimumNetProfit = 0.4
const val buyWeight = 2.0
data class AppConfig(
// [DB 저장 데이터]

View File

@ -20,6 +20,7 @@ import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
import model.buyWeight
import model.feesAndTaxRate
import model.minimumNetProfit
import network.KisTradeService
@ -72,7 +73,7 @@ fun IntegratedOrderSection(
}
var profitRate by remember(monitoringItem) {
mutableStateOf(monitoringItem?.profitRate?.toString() ?: "0.8")
mutableStateOf(monitoringItem?.profitRate?.toString() ?: minimumNetProfit.toString())
}
var stopLossRate by remember(monitoringItem) {
mutableStateOf(monitoringItem?.stopLossRate?.toString() ?: "-1.5")
@ -83,7 +84,7 @@ fun IntegratedOrderSection(
val basePrice = (if (orderPrice.isEmpty()) curPriceNum else orderPrice.toDoubleOrNull() ?: 0.0)
val inputQty = orderQty.replace(",", "").toIntOrNull() ?: 0
fun excuteTrade(willEnableAutoSell: Boolean,orderQty: String) {
fun excuteTrade(willEnableAutoSell: Boolean, orderQty: String, profitRate1: Double?) {
scope.launch {
val tickSize = MarketUtil.getTickSize(basePrice)
val oneTickLowerPrice = basePrice - tickSize
@ -108,7 +109,7 @@ fun IntegratedOrderSection(
// 3. 실질 목표 수익률 계산
// 사용자가 입력한 pRate와 (최소 순수익 + 제반 비용) 중 큰 값을 선택합니다.
val effectiveProfitRate = maxOf(pRate, minimumNetProfit + feesAndTaxRate)
val effectiveProfitRate = maxOf((profitRate1 ?: pRate) + feesAndTaxRate, minimumNetProfit + feesAndTaxRate)
// 4. 보정된 수익률을 적용하여 목표가 계산
val calculatedTarget = MarketUtil.roundToTickSize(basePrice * (1 + effectiveProfitRate / 100.0))
@ -152,25 +153,50 @@ fun IntegratedOrderSection(
profitPossible : ${completeTradingDecision.profitPossible()+ append}
safePossible : ${completeTradingDecision.safePossible()+ append}
""".trimIndent())
// 2. 조건 검사: 신뢰도 80 이상 AND 중기 점수 70 이상
if (completeTradingDecision.confidence + append >= MIN_CONFIDENCE &&
completeTradingDecision.shortPossible() + append >= MIN_SHORT_SCORE &&
completeTradingDecision.profitPossible() + append >= MIN_POSSIBLE_SCORE &&
completeTradingDecision.safePossible() + append >= MIN_SAFE_SCORE
) {
println("🚀 [조건 만족] 강력 매수 시그널 포착 -> 자동 매수 진행 (1주) ${completeTradingDecision.stockCode}")
// 3. 매수 실행 (자동 감시 켜기: true, 수량: 1주)
// 수량은 필요에 따라 로직으로 계산하여 변경 가능 (예: 자산의 10% 등)
excuteTrade(willEnableAutoSell = true, orderQty = "1")
val weights = mapOf(
"short" to 0.3, // 초단기 점수가 낮아도 전체에 미치는 영향 감소
"profit" to 0.3,
"safe" to 0.4 // 중장기 점수 비중 강화
)
// 2. 토탈 스코어 계산
val totalScore =
(completeTradingDecision.shortPossible() * weights["short"]!!) +
(completeTradingDecision.profitPossible() * weights["profit"]!!) +
(completeTradingDecision.safePossible() * weights["safe"]!!)
// 3. 매수 결정 문턱값 (예: 70점 이상이면 매수 가능)
val MIN_PURCHASE_SCORE = 70.0
val HIGH_QUALITY_SCORE = 85.0 // 강력 추천 기준
if (totalScore >= MIN_PURCHASE_SCORE && completeTradingDecision.confidence > MIN_CONFIDENCE) {
// 4. 점수에 따른 가변 마진 적용
// 토탈 스코어가 85점 이상이면 마진을 3.0으로 고정하거나 추가 가산(append) 적용
val finalMargin = if (totalScore >= HIGH_QUALITY_SCORE) {
println("💎 [우량주 포착] 토탈 스코어($totalScore)가 매우 높아 목표 마진을 3.0%로 상향합니다.")
minimumNetProfit + (append * 1.5)
} else {
minimumNetProfit + append
}
println("🚀 [매수 진행] 토탈 스코어: ${String.format("%.1f", totalScore)} -> 종목: ${completeTradingDecision.stockCode}")
// 5. 매수 실행 (계산된 finalMargin 전달)
excuteTrade(
willEnableAutoSell = true,
orderQty = "1",
profitRate1 = finalMargin
)
} else {
println("✋ [조건 미달] 매수 의견이나 점수 부족으로 관망")
println("✋ [관망] 토탈 스코어(${String.format("%.1f", totalScore)})가 기준치($MIN_PURCHASE_SCORE) 미달")
}
}
when (completeTradingDecision?.decision) {
"BUY" -> {
append = 3.0
append = buyWeight
println("[$stockCode] 매수 추천 resultCheck: ${completeTradingDecision?.reason}")
resultCheck(completeTradingDecision)
}
@ -274,7 +300,7 @@ fun IntegratedOrderSection(
// 매수 버튼
Button(
onClick = {
excuteTrade(willEnableAutoSell,orderQty)
excuteTrade(willEnableAutoSell, orderQty, profitRate.toDouble())
},
modifier = Modifier.weight(1f).padding(end = 4.dp),
colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFFE03E2D))