커뮤니티
K-means 클러스터링(K-means clustering)
5일(기본입력값) 고가 돌파매수 저가 이탈매도 지표식을
AI(클러스터링) 방식으로 동적으로 선택하도록 설계한 예스트레이더용 구현 템플릿을 AI 질문했더니
아래처럼 제공했습니다만 예스랭귀지에 사용 부적합인지라
iM증권 예스트레이더에 부합하는 코드로 변환을 부탁드립니다.
// === 입력값 ===
input minN = 3
input maxN = 10
input stepN = 1
input perfMemory = 10 // 지수평활(미사용 시 단순평가)
input fromCluster = "Best" // "Best" / "Average" / "Worst"
input maxIter = 100
input maxBars = 1000 // 과거 평가용 봉 수
input defaultN = 5 // 안전 기본값
// === 후보 N 목록 생성 ===
var array<int> candN = array.new()
for n = minN to maxN step stepN
array.push(candN, n)
endfor
// === 각 후보의 퍼포먼스 계산 (단순 누적 수익) ===
var array<float> perfList = array.new()
var array<int> factorList = array.new()
// 현재 BAR_COUNT(플랫폼에 따라 이름 다를 수 있음)
barsToEvaluate = min(barcount(), maxBars)
// for each candidate N, 시뮬레이션
for idx = 0 to array.size(candN)-1
N = array.get(candN, idx)
cash = 0.0
position = 0 // 0=flat, 1=long
entry_price = 0.0
// 시간 흐름: 오래된 -> 최신 (플랫폼 루프 방법에 따라 조정)
// 여기서는 i는 과거 offset (barsToEvaluate downto 1)
for offset = barsToEvaluate down to 1
// 전봉 기준 N기간 최고/최저 (함수명: HHV / LLV 또는 highest/lowest 로 바꿔서 사용)
hh = HHV(high, N, offset) // = offset번째 시점에서의 N기간 최고 (함수명 확인 필요)
ll = LLV(low, N, offset)
// 현재 바의 종가 (offset 시점)
c = ref(close, offset)
// 진입: 종가가 전봉 기준 N기간 최고 돌파 (전략 규칙)
if position == 0 and c > hh
position = 1
entry_price = c
endif
// 청산: 포지션 중 저가 이탈
if position == 1 and c < ll
profit = c - entry_price
cash = cash + profit
position = 0
entry_price = 0.0
endif
endfor
// 시뮬레이션 종료 시 미청산 포지션 정리(평가 목적)
if position == 1
last_close = close // 최신 종가
cash = cash + (last_close - entry_price)
endif
array.push(perfList, cash)
array.push(factorList, N)
endfor
// === 퍼포먼스 값에서 초기 centroid 계산 (25/50/75 percentile) ===
// 플랫폼에 percentile 함수가 없다면 간단 정렬 후 인덱스로 대체 가능
perf_sorted = array.copy(perfList)
array.sort(perf_sorted) // 오름차순
sizeP = array.size(perf_sorted)
p25_idx = max(0, floor(0.25 * (sizeP - 1)))
p50_idx = max(0, floor(0.50 * (sizeP - 1)))
p75_idx = max(0, floor(0.75 * (sizeP - 1)))
centroids = array.new()
array.push(centroids, array.get(perf_sorted, p25_idx))
array.push(centroids, array.get(perf_sorted, p50_idx))
array.push(centroids, array.get(perf_sorted, p75_idx))
// === K-means 1D 반복 ===
for iter = 1 to maxIter
// 초기화
clusters_perf = array.from(array.new(), array.new(), array.new())
clusters_factor = array.from(array.new(), array.new(), array.new())
// 할당 단계
for i = 0 to array.size(perfList)-1
val = array.get(perfList, i)
// 거리 계산
d0 = abs(val - array.get(centroids, 0))
d1 = abs(val - array.get(centroids, 1))
d2 = abs(val - array.get(centroids, 2))
// 가장 작은 거리 인덱스 선택
idx_min = 0
if d1 < d0
idx_min = 1
if d2 < d1
idx_min = 2
endif
else
if d2 < d0
idx_min = 2
endif
endif
// 클러스터에 추가
array.push(array.get(clusters_perf, idx_min), val)
array.push(array.get(clusters_factor, idx_min), array.get(factorList, i))
endfor
// 중심 재계산
new_centroids = array.new()
for k = 0 to 2
cperf = array.get(clusters_perf, k)
if array.size(cperf) > 0
sumv = 0.0
for j = 0 to array.size(cperf)-1
sumv = sumv + array.get(cperf, j)
endfor
avgv = sumv / array.size(cperf)
array.push(new_centroids, avgv)
else
// 빈 클러스터는 기존 centroid 유지
array.push(new_centroids, array.get(centroids, k))
endif
endfor
// 수렴 체크 (모두 같다면 종료)
if array.get(new_centroids,0) == array.get(centroids,0) and
array.get(new_centroids,1) == array.get(centroids,1) and
array.get(new_centroids,2) == array.get(centroids,2)
break
endif
centroids := new_centroids
endfor
// === 선택 클러스터 매핑 ('Worst'=0, 'Average'=1, 'Best'=2) ===
selIdx = 2
if fromCluster == "Worst" then selIdx = 0 endif
if fromCluster == "Average" then selIdx = 1 endif
// 선택 클러스터의 평균 N 계산 (없으면 기본값)
chosenN = defaultN
sel_factors = array.get(clusters_factor, selIdx)
if array.size(sel_factors) > 0
ssum = 0
for i = 0 to array.size(sel_factors)-1
ssum = ssum + array.get(sel_factors, i)
endfor
chosenN = round(ssum / array.size(sel_factors))
endif
// === 실시간 시그널: chosenN 사용 ===
// 최신 N기간 최고/최저 계산 (함수명 HHV/LLV 사용)
curr_hh = HHV(high, chosenN)
curr_ll = LLV(low, chosenN)
buySignal = close > curr_hh
sellSignal = close < curr_ll
// 출력(화면 및 알림용)
plot_int("ChosenN", chosenN)
plot_bool("Buy", buySignal)
plot_bool("Sell", sellSignal)
// 실제 주문/포지션 관리는 전략 엔진 규칙에 맞춰 작성
답변 1
예스스탁 예스스탁 답변
2025-10-27 17:06:23