...
This commit is contained in:
@@ -247,8 +247,8 @@ class TradeConfig {
|
||||
var ONE_STOCK_ALYSIS_TIME = 180000L
|
||||
var isLowPerformanceMonitoring: Boolean = false
|
||||
var useGradeShare : List<String> = listOf("LEVEL_4","LEVEL_5")
|
||||
var useTagsShare : List<String> = listOf("NOTICE", "WATCH","매도 완료")
|
||||
var useLogKeywordsShare : List<String> = listOf("재분석")
|
||||
var useTagsShare : List<String> = listOf("NOTICE", "WATCH")
|
||||
var useLogKeywordsShare : List<String> = listOf("재분석","매도 완료")
|
||||
var useAutoRepost : Boolean = false
|
||||
var minusFilter : Double = 15.0
|
||||
var plusFilter : Double = 15.0
|
||||
@@ -268,6 +268,8 @@ class TradeConfig {
|
||||
var maxExpectedReboundDays: Double = 10.0 // 필터링 기준 최대 허용 반등 주기 (일)
|
||||
var minExpectedReboundDays: Double = 1.5
|
||||
var isUpcomingDividend : Boolean = false
|
||||
var buyTickOffset : Int = 4
|
||||
var sellTickOffset : Int = 4
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ object AutoTradingManager {
|
||||
|
||||
val price1 = finalPrice
|
||||
// 2차 매수는 1차 매수가보다 3호가 아래에 대기 (더 싼 가격에 줍기)
|
||||
val price2 = MarketUtil.roundToTickSize(price1 - (tickSize * 3))
|
||||
val price2 = MarketUtil.roundToTickSize(price1 - (tickSize * KisSession.tradeConfig.buyTickOffset))
|
||||
|
||||
println("🔄 [분할 매수 진입] $stockName 1차(${qty1}주 / $price1) | 2차(${qty2}주 / $price2)")
|
||||
|
||||
@@ -574,7 +574,7 @@ object AutoTradingManager {
|
||||
val qty2 = totalQty - qty1 // 나머지 (4호가 위)
|
||||
|
||||
val price1 = currentPrice
|
||||
val price2 = MarketUtil.roundToTickSize(currentPrice + (MarketUtil.getTickSize(currentPrice) * 4))
|
||||
val price2 = MarketUtil.roundToTickSize(currentPrice + (MarketUtil.getTickSize(currentPrice) * KisSession.tradeConfig.sellTickOffset))
|
||||
|
||||
TradingLogStore.addAfterMarketLog(
|
||||
holding.name,
|
||||
@@ -639,7 +639,7 @@ object AutoTradingManager {
|
||||
"${holding.name}[${holding.code}]",
|
||||
price2.toString(),
|
||||
"SELL",
|
||||
"🎊 ${if (marketCode == "Y") "시간외 단일가" else "대체거래소"} 2차 분할매도(4호가 위) ${qty2}주 매도 완료"
|
||||
"🎊 ${if (marketCode == "Y") "시간외 단일가" else "대체거래소"} 2차 분할매도(${KisSession.tradeConfig.sellTickOffset}호가 위) ${qty2}주 매도 완료"
|
||||
)
|
||||
DatabaseFactory.saveAutoTrade(
|
||||
AutoTradeItem(
|
||||
@@ -766,9 +766,10 @@ object AutoTradingManager {
|
||||
val qty2 = totalQty - qty1
|
||||
|
||||
val price1 = currentPrice
|
||||
val price2 = MarketUtil.roundToTickSize(currentPrice + (MarketUtil.getTickSize(currentPrice) * 4))
|
||||
val price2 = MarketUtil.roundToTickSize(currentPrice + (MarketUtil.getTickSize(currentPrice) * KisSession.tradeConfig.sellTickOffset))
|
||||
|
||||
println("🔄 [보유 주식 주문] ${holding.name} (${holding.code}) 분할 매도: 현재가($price1) ${qty1}주, 4호가 위($price2) ${qty2}주")
|
||||
|
||||
println("🔄 [보유 주식 주문] ${holding.name} (${holding.code}) 분할 매도: 현재가($price1) ${qty1}주, ${KisSession.tradeConfig.sellTickOffset}호가 위($price2) ${qty2}주")
|
||||
|
||||
// 1차 매도: 현재가
|
||||
if (qty1 > 0) {
|
||||
@@ -1499,9 +1500,7 @@ object AutoTradingManager {
|
||||
if (corpInfo?.cName.isNullOrEmpty()) return@withTimeout
|
||||
|
||||
// 🌟 [핵심] 물타기 대상 여부 플래그 식별
|
||||
val targetHolding = currentBalance?.getHoldings()?.firstOrNull {
|
||||
it.code == stock.code && it.quantity.toInt() > KisSession.tradeConfig.lowerAverageTargetCount
|
||||
}
|
||||
val targetHolding = currentBalance?.getHoldings()?.firstOrNull { it.code == stock.code && it.quantity.toInt() > 0 }
|
||||
val isWatering = targetHolding != null && KisSession.tradeConfig.lowerAveragePrice
|
||||
|
||||
if (isWatering) {
|
||||
@@ -1570,7 +1569,7 @@ object AutoTradingManager {
|
||||
// 🌟 [완화 3] 기대수익률 및 진입 타이밍 이원화
|
||||
val isProfitable: Boolean
|
||||
val isValidEntryTiming: Boolean
|
||||
|
||||
val isSteadyUptrend = tempAnalyzer.checkSteadyUptrend(dailyData)
|
||||
if (isWatering) {
|
||||
// 물타기: 평단 낮추기 목적이므로 기대수익률 1.0% 이상이면 충분
|
||||
isProfitable = expectedProfitRate >= 1.0 || dailyStats.avgReboundAmplitude >= 1.5
|
||||
@@ -1586,7 +1585,7 @@ object AutoTradingManager {
|
||||
} else {
|
||||
// 신규 진입: 기존 엄격 기준 유지
|
||||
isProfitable = expectedProfitRate >= KisSession.tradeConfig.minExpectedProfitRate ||
|
||||
dailyStats.avgReboundAmplitude >= KisSession.tradeConfig.minExpectedProfitRate
|
||||
(dailyStats.avgReboundAmplitude.times(0.8)) >= KisSession.tradeConfig.minExpectedProfitRate
|
||||
|
||||
val isApproaching = tempAnalyzer.checkReboundApproaching(
|
||||
dailyData, dailyStats.avgReboundPeriod, dailyStats.avgDropRate, dailyStats.timeTolerance
|
||||
@@ -1594,12 +1593,12 @@ object AutoTradingManager {
|
||||
isValidEntryTiming = (dailyStats.isValid && isApproaching &&
|
||||
dailyStats.avgReboundPeriod <= KisSession.tradeConfig.maxExpectedReboundDays &&
|
||||
dailyStats.avgReboundPeriod >= KisSession.tradeConfig.minExpectedReboundDays) ||
|
||||
tempAnalyzer.checkSteadyUptrend(dailyData)
|
||||
isSteadyUptrend
|
||||
}
|
||||
|
||||
val currentAtr = tempAnalyzer.calculateATR(dailyData)
|
||||
if (!isProfitable || !isValidEntryTiming) {
|
||||
println("-> [${stock.name}] 목표 수익 조건 미달 (물타기:$isWatering, 수익:$isProfitable, 타이밍:$isValidEntryTiming) | 기대 수익율 : ${expectedProfitRate} || ${dailyStats.avgReboundAmplitude}")
|
||||
println("-> [${stock.name}] 목표 수익 조건 미달 (물타기:$isWatering, 수익:$isProfitable, 타이밍:$isValidEntryTiming, 우상향:$isSteadyUptrend) | 기대 수익율 : ${expectedProfitRate} || ${dailyStats.avgReboundAmplitude}")
|
||||
return@withTimeout
|
||||
}
|
||||
|
||||
|
||||
@@ -729,6 +729,29 @@ fun TradingDecisionLog() {
|
||||
)
|
||||
}
|
||||
|
||||
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
|
||||
SettingInputField(
|
||||
modifier = Modifier.weight(1.0f, true),
|
||||
label = "분할 매수시",
|
||||
initialValue = (tradeConfig.buyTickOffset).toString(),
|
||||
onSave = {
|
||||
tradeConfig.buyTickOffset = it.toInt()
|
||||
KisSession.saveTradeConfig()
|
||||
},
|
||||
helperText = "매수가 기준 아래 호가로 분할 매수"
|
||||
)
|
||||
SettingInputField(
|
||||
modifier = Modifier.weight(1.0f, true),
|
||||
label = "분할 매도시",
|
||||
initialValue = (tradeConfig.sellTickOffset).toString(),
|
||||
onSave = {
|
||||
tradeConfig.sellTickOffset = it.toInt()
|
||||
KisSession.saveTradeConfig()
|
||||
},
|
||||
helperText = "매수가 기준 위 호가로 분할 매수"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user