추세검색 수정

This commit is contained in:
Macbook
2026-05-27 00:28:09 +09:00
parent fe812389cc
commit c1bcf88c6c
10 changed files with 631 additions and 287 deletions
@@ -0,0 +1,114 @@
/** 상승추세 검색그룹 — 5개 평가항목 배점 (합계 100 고정) */
export type BullishWeightKey =
| 'weightMaAlignment'
| 'weightMaSlope'
| 'weightAdxTrend'
| 'weightMacdMomentum'
| 'weightPricePosition';
export interface BullishWeightItem {
key: BullishWeightKey;
label: string;
desc: string;
}
export const BULLISH_WEIGHT_ITEMS: BullishWeightItem[] = [
{
key: 'weightMaAlignment',
label: '이평선 정배열',
desc: 'EMA(20) > EMA(60) > EMA(120)',
},
{
key: 'weightMaSlope',
label: '이평선 기울기',
desc: 'EMA(20) 현재 > 5봉 전',
},
{
key: 'weightAdxTrend',
label: '추세강도 (ADX)',
desc: '+DI > -DI · ADX ≥ 20',
},
{
key: 'weightMacdMomentum',
label: '모멘텀 (MACD)',
desc: 'MACD > Signal · MACD > 0',
},
{
key: 'weightPricePosition',
label: '가격위치',
desc: '종가 > EMA(20)',
},
];
export const DEFAULT_BULLISH_WEIGHTS: Record<BullishWeightKey, number> = {
weightMaAlignment: 30,
weightMaSlope: 15,
weightAdxTrend: 25,
weightMacdMomentum: 15,
weightPricePosition: 15,
};
export function bullishWeightsFromRequest(
req: Pick<import('./backendApi').TrendSearchRequest, BullishWeightKey>,
): number[] {
return BULLISH_WEIGHT_ITEMS.map(item => req[item.key] ?? DEFAULT_BULLISH_WEIGHTS[item.key]);
}
export function sumWeights(weights: number[]): number {
return weights.reduce((a, b) => a + b, 0);
}
/**
* 한 항목 배점 변경 시 나머지 항목에 차이를 균등 분배해 합계 100 유지.
*/
export function adjustBullishWeight(
current: Record<BullishWeightKey, number>,
changedKey: BullishWeightKey,
newValue: number,
): Record<BullishWeightKey, number> {
const keys = BULLISH_WEIGHT_ITEMS.map(i => i.key);
const idx = keys.indexOf(changedKey);
if (idx < 0) return current;
const clamped = Math.max(0, Math.min(100, Math.round(newValue)));
const oldValue = current[changedKey];
if (clamped === oldValue) return current;
const result: Record<BullishWeightKey, number> = { ...current };
result[changedKey] = clamped;
const delta = clamped - oldValue;
const otherKeys = keys.filter(k => k !== changedKey);
if (delta > 0) {
let remaining = delta;
for (let i = 0; i < otherKeys.length; i++) {
const k = otherKeys[i];
const take = i === otherKeys.length - 1
? remaining
: Math.floor(delta / otherKeys.length);
result[k] = Math.max(0, result[k] - take);
remaining -= take;
}
} else {
const add = Math.abs(delta);
let remaining = add;
for (let i = 0; i < otherKeys.length; i++) {
const k = otherKeys[i];
const give = i === otherKeys.length - 1
? remaining
: Math.floor(add / otherKeys.length);
result[k] += give;
remaining -= give;
}
}
const total = keys.reduce((s, k) => s + result[k], 0);
if (total !== 100) {
const fixKey = otherKeys[0] ?? changedKey;
result[fixKey] = Math.max(0, result[fixKey] + (100 - total));
}
return result;
}