가상투자 종목카드박스 레이아웃 수정

This commit is contained in:
Macbook
2026-05-26 16:42:57 +09:00
parent 7cf43609dc
commit c0d21ac825
25 changed files with 1632 additions and 61 deletions
+66 -2
View File
@@ -1,5 +1,6 @@
import type { LogicNode } from './strategyTypes';
import { genId, type DefType } from './strategyEditorShared';
import { nhPriorField, nlPriorField } from './priceExtremeIndicators';
export type SimpleStrategyTemplate = {
kind: 'simple';
@@ -10,6 +11,7 @@ export type SimpleStrategyTemplate = {
cond: string;
l: string;
r: string;
period?: number;
};
export type CompositeStrategyTemplate = {
@@ -28,11 +30,19 @@ function condition(
leftField: string,
rightField: string,
candleRange = 1,
period?: number,
): LogicNode {
return {
id: genId(),
type: 'CONDITION',
condition: { indicatorType, conditionType, leftField, rightField, candleRange },
condition: {
indicatorType,
conditionType,
leftField,
rightField,
candleRange,
...(period != null ? { period } : null),
},
};
}
@@ -50,6 +60,16 @@ function donchianBreakdownSell(period: number): LogicNode {
return condition('DONCHIAN', 'CROSS_DOWN', 'CLOSE_PRICE', `DC_LOWER_${period}`);
}
/** N일 신고가 돌파 — 종가가 직전 N봉 최고가를 상향 돌파 */
function newHighBreakoutBuy(period: number): LogicNode {
return condition('NEW_HIGH', 'CROSS_UP', 'CLOSE_PRICE', nhPriorField(period), 1, period);
}
/** N일 신저가 이탈 — 종가가 직전 N봉 최저가를 하향 이탈 */
function newLowBreakdownSell(period: number): LogicNode {
return condition('NEW_LOW', 'CROSS_DOWN', 'CLOSE_PRICE', nlPriorField(period), 1, period);
}
/** 일목균형표 — 전환선(9일) / 기준선(26일) 골든·데드크로스 */
function ichimokuTenkanKijunCross(signal: 'buy' | 'sell'): LogicNode {
return condition(
@@ -99,6 +119,50 @@ export function getStrategyTemplates(def: DefType): StrategyTemplateDef[] {
{ kind: 'simple', ind: 'PSYCHOLOGICAL', cond: 'CROSS_UP', l: 'PSY_VALUE', r: 'OVERBOUGHT_75', signal: 'buy', label: '심리도 상향 돌파' },
{ kind: 'simple', ind: 'STOCHASTIC', cond: 'CROSS_UP', l: 'STOCH_K', r: 'STOCH_D', signal: 'buy', label: '스토캐스틱 골든크로스' },
{ kind: 'simple', ind: 'ADX', cond: 'CROSS_UP', l: 'ADX_VALUE', r: 'ADX_25', signal: 'buy', label: 'ADX 중앙선 상향 돌파' },
{
kind: 'simple',
ind: 'NEW_HIGH',
cond: 'CROSS_UP',
l: 'CLOSE_PRICE',
r: nhPriorField(9),
period: 9,
signal: 'buy',
label: '9일 신고가 돌파',
description: '종가가 직전 9봉 최고가 이상 — 단기 박스권 상단 돌파 매수',
},
{
kind: 'simple',
ind: 'NEW_HIGH',
cond: 'CROSS_UP',
l: 'CLOSE_PRICE',
r: nhPriorField(20),
period: 20,
signal: 'buy',
label: '20일 신고가 돌파',
description: '종가가 직전 20봉 최고가 이상 — 한 달 박스 돌파 매수',
},
{
kind: 'simple',
ind: 'NEW_LOW',
cond: 'CROSS_DOWN',
l: 'CLOSE_PRICE',
r: nlPriorField(9),
period: 9,
signal: 'sell',
label: '9일 신저가 이탈',
description: '종가가 직전 9봉 최저가 이하 — 단기 지지 붕괴 매도/손절',
},
{
kind: 'simple',
ind: 'NEW_LOW',
cond: 'CROSS_DOWN',
l: 'CLOSE_PRICE',
r: nlPriorField(20),
period: 20,
signal: 'sell',
label: '20일 신저가 이탈',
description: '종가가 직전 20봉 최저가 이하 — 추세 이탈 청산',
},
{
kind: 'composite',
signal: 'buy',
@@ -173,5 +237,5 @@ export function getStrategyTemplates(def: DefType): StrategyTemplateDef[] {
}
export function simpleTemplateToNode(tmpl: SimpleStrategyTemplate): LogicNode {
return condition(tmpl.ind, tmpl.cond, tmpl.l, tmpl.r);
return condition(tmpl.ind, tmpl.cond, tmpl.l, tmpl.r, 1, tmpl.period);
}