전체적인 리팩토링
This commit is contained in:
482
features/autotrade/types/autotrade.types.ts
Normal file
482
features/autotrade/types/autotrade.types.ts
Normal file
@@ -0,0 +1,482 @@
|
||||
/**
|
||||
* @file features/autotrade/types/autotrade.types.ts
|
||||
* @description 자동매매 기능에서 공통으로 사용하는 타입 정의입니다.
|
||||
*/
|
||||
|
||||
export const AUTOTRADE_TECHNIQUE_IDS = [
|
||||
"orb",
|
||||
"vwap_reversion",
|
||||
"volume_breakout",
|
||||
"ma_crossover",
|
||||
"gap_breakout",
|
||||
"intraday_box_reversion",
|
||||
"intraday_breakout_scalp",
|
||||
] as const;
|
||||
|
||||
export type AutotradeTechniqueId = (typeof AUTOTRADE_TECHNIQUE_IDS)[number];
|
||||
|
||||
export interface AutotradeTechniqueOption {
|
||||
id: AutotradeTechniqueId;
|
||||
label: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export const AUTOTRADE_TECHNIQUE_OPTIONS: AutotradeTechniqueOption[] = [
|
||||
{
|
||||
id: "orb",
|
||||
label: "ORB(시가 범위 돌파)",
|
||||
description: "시가 근처 범위를 돌파할 때 추세 진입 신호를 확인합니다.",
|
||||
},
|
||||
{
|
||||
id: "vwap_reversion",
|
||||
label: "VWAP 되돌림",
|
||||
description: "VWAP에서 과하게 이탈한 가격이 평균으로 복귀하는 구간을 봅니다.",
|
||||
},
|
||||
{
|
||||
id: "volume_breakout",
|
||||
label: "거래량 돌파",
|
||||
description: "거래량 급증과 함께 방향성이 생기는 순간을 포착합니다.",
|
||||
},
|
||||
{
|
||||
id: "ma_crossover",
|
||||
label: "이동평균 교차",
|
||||
description: "단기/중기 평균선 교차로 추세 전환 여부를 확인합니다.",
|
||||
},
|
||||
{
|
||||
id: "gap_breakout",
|
||||
label: "갭 돌파",
|
||||
description: "갭 상승/하락 이후 추가 돌파 또는 되돌림을 판단합니다.",
|
||||
},
|
||||
{
|
||||
id: "intraday_box_reversion",
|
||||
label: "상승 후 박스권 단타",
|
||||
description:
|
||||
"당일 상승 이후 박스권 횡보 구간에서 상단/하단 왕복(오르락내리락) 단타를 노립니다.",
|
||||
},
|
||||
{
|
||||
id: "intraday_breakout_scalp",
|
||||
label: "상승구간 눌림-재돌파 단타",
|
||||
description:
|
||||
"1분봉 상승 추세에서 저거래량 눌림 후 고점 재돌파(거래량 재유입) 구간을 노립니다.",
|
||||
},
|
||||
];
|
||||
|
||||
export const AUTOTRADE_DEFAULT_TECHNIQUES: AutotradeTechniqueId[] = [
|
||||
"ma_crossover",
|
||||
"vwap_reversion",
|
||||
"intraday_box_reversion",
|
||||
"intraday_breakout_scalp",
|
||||
];
|
||||
|
||||
export type AutotradeEngineState =
|
||||
| "IDLE"
|
||||
| "RUNNING"
|
||||
| "STOPPING"
|
||||
| "STOPPED"
|
||||
| "ERROR";
|
||||
|
||||
export const AUTOTRADE_AI_MODE_IDS = [
|
||||
"auto",
|
||||
"openai_api",
|
||||
"subscription_cli",
|
||||
"rule_fallback",
|
||||
] as const;
|
||||
|
||||
export type AutotradeAiMode = (typeof AUTOTRADE_AI_MODE_IDS)[number];
|
||||
|
||||
export const AUTOTRADE_SUBSCRIPTION_CLI_VENDOR_IDS = [
|
||||
"auto",
|
||||
"codex",
|
||||
"gemini",
|
||||
] as const;
|
||||
|
||||
export type AutotradeSubscriptionCliVendor =
|
||||
(typeof AUTOTRADE_SUBSCRIPTION_CLI_VENDOR_IDS)[number];
|
||||
|
||||
export interface AutotradeSubscriptionCliVendorOption {
|
||||
id: AutotradeSubscriptionCliVendor;
|
||||
label: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export const AUTOTRADE_SUBSCRIPTION_CLI_VENDOR_OPTIONS: AutotradeSubscriptionCliVendorOption[] =
|
||||
[
|
||||
{
|
||||
id: "auto",
|
||||
label: "자동 선택",
|
||||
description: "Codex -> Gemini 순서로 시도합니다.",
|
||||
},
|
||||
{
|
||||
id: "codex",
|
||||
label: "Codex CLI",
|
||||
description: "OpenAI Codex CLI만 사용합니다.",
|
||||
},
|
||||
{
|
||||
id: "gemini",
|
||||
label: "Gemini CLI",
|
||||
description: "Google Gemini CLI만 사용합니다.",
|
||||
},
|
||||
];
|
||||
|
||||
export interface AutotradeSubscriptionCliModelOption {
|
||||
value: string;
|
||||
label: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
// [출처] 공식 문서 기준 추천 프리셋
|
||||
// - Codex Models: https://developers.openai.com/codex/models
|
||||
// - Gemini CLI model command: https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/model.md
|
||||
export const AUTOTRADE_SUBSCRIPTION_CLI_MODEL_OPTIONS = {
|
||||
codex: [
|
||||
{
|
||||
value: "gpt-5.4",
|
||||
label: "gpt-5.4",
|
||||
description: "Codex 추천 기본형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5.3-codex",
|
||||
label: "gpt-5.3-codex",
|
||||
description: "Codex 5.3 고성능 라인",
|
||||
},
|
||||
{
|
||||
value: "gpt-5.3-codex-spark",
|
||||
label: "gpt-5.3-codex-spark",
|
||||
description: "Codex 5.3 경량형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5.2-codex",
|
||||
label: "gpt-5.2-codex",
|
||||
description: "Codex 5.2 균형형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5.2",
|
||||
label: "gpt-5.2",
|
||||
description: "Codex 5.2 범용형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5.1-codex-max",
|
||||
label: "gpt-5.1-codex-max",
|
||||
description: "문맥 확장형 Codex 5.1",
|
||||
},
|
||||
{
|
||||
value: "gpt-5.1",
|
||||
label: "gpt-5.1",
|
||||
description: "Codex 5.1 범용형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5.1-codex",
|
||||
label: "gpt-5.1-codex",
|
||||
description: "Codex 5.1 기본형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5-codex",
|
||||
label: "gpt-5-codex (안정형)",
|
||||
description: "Codex 안정형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5-codex-mini",
|
||||
label: "gpt-5-codex-mini",
|
||||
description: "Codex 경량형",
|
||||
},
|
||||
{
|
||||
value: "gpt-5",
|
||||
label: "gpt-5",
|
||||
description: "Codex 범용 경량 라인",
|
||||
},
|
||||
] satisfies AutotradeSubscriptionCliModelOption[],
|
||||
gemini: [
|
||||
{
|
||||
value: "auto",
|
||||
label: "auto (권장)",
|
||||
description: "상황에 따라 Pro/Flash 계열을 자동 선택",
|
||||
},
|
||||
{
|
||||
value: "gemini-3.1-pro-preview",
|
||||
label: "gemini-3.1-pro-preview (신규)",
|
||||
description: "Gemini 3.1 고성능 추론/코딩 프리뷰",
|
||||
},
|
||||
{
|
||||
value: "gemini-3.1-flash-lite-preview",
|
||||
label: "gemini-3.1-flash-lite-preview",
|
||||
description: "Gemini 3.1 경량 고속 프리뷰",
|
||||
},
|
||||
{
|
||||
value: "gemini-3-flash-preview",
|
||||
label: "gemini-3-flash-preview",
|
||||
description: "Gemini 3 고속 프리뷰",
|
||||
},
|
||||
{
|
||||
value: "gemini-2.5-pro",
|
||||
label: "gemini-2.5-pro",
|
||||
description: "고난도 추론 중심",
|
||||
},
|
||||
{
|
||||
value: "gemini-2.5-flash",
|
||||
label: "gemini-2.5-flash",
|
||||
description: "속도/품질 균형형",
|
||||
},
|
||||
{
|
||||
value: "gemini-2.5-flash-lite",
|
||||
label: "gemini-2.5-flash-lite",
|
||||
description: "가벼운 작업용 고속 모델",
|
||||
},
|
||||
{
|
||||
value: "gemini-3-pro-preview",
|
||||
label: "gemini-3-pro-preview (종료예정)",
|
||||
description: "공식 문서 기준 2026-03-09 종료 예정 프리뷰",
|
||||
},
|
||||
] satisfies AutotradeSubscriptionCliModelOption[],
|
||||
} as const;
|
||||
|
||||
export interface AutotradeAiModeOption {
|
||||
id: AutotradeAiMode;
|
||||
label: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export const AUTOTRADE_AI_MODE_OPTIONS: AutotradeAiModeOption[] = [
|
||||
{
|
||||
id: "auto",
|
||||
label: "자동(권장)",
|
||||
description:
|
||||
"OpenAI API 키가 있으면 OpenAI를 사용하고, 없으면 구독형 CLI를 시도합니다. 둘 다 실패하면 규칙 기반으로 전환합니다.",
|
||||
},
|
||||
{
|
||||
id: "openai_api",
|
||||
label: "OpenAI API",
|
||||
description: "서버에서 OpenAI API를 직접 호출해 판단합니다.",
|
||||
},
|
||||
{
|
||||
id: "subscription_cli",
|
||||
label: "구독형 CLI 자동판단",
|
||||
description: "서버에 설치된 Codex/Gemini CLI로 자동 판단을 생성합니다.",
|
||||
},
|
||||
{
|
||||
id: "rule_fallback",
|
||||
label: "규칙 기반",
|
||||
description: "AI 호출 없이 내부 규칙 엔진으로만 판단합니다.",
|
||||
},
|
||||
];
|
||||
|
||||
export type AutotradeStopReason =
|
||||
| "browser_exit"
|
||||
| "external_leave"
|
||||
| "manual"
|
||||
| "emergency"
|
||||
| "heartbeat_timeout";
|
||||
|
||||
export interface AutotradeSetupFormValues {
|
||||
aiMode: AutotradeAiMode;
|
||||
subscriptionCliVendor: AutotradeSubscriptionCliVendor;
|
||||
subscriptionCliModel: string;
|
||||
prompt: string;
|
||||
selectedTechniques: AutotradeTechniqueId[];
|
||||
allocationPercent: number;
|
||||
allocationAmount: number;
|
||||
dailyLossPercent: number;
|
||||
dailyLossAmount: number;
|
||||
confidenceThreshold: number;
|
||||
agreeStopOnExit: boolean;
|
||||
}
|
||||
|
||||
export interface AutotradeCompiledStrategy {
|
||||
provider: "openai" | "fallback" | "subscription_cli";
|
||||
providerVendor?: "codex" | "gemini";
|
||||
providerModel?: string;
|
||||
summary: string;
|
||||
selectedTechniques: AutotradeTechniqueId[];
|
||||
confidenceThreshold: number;
|
||||
maxDailyOrders: number;
|
||||
cooldownSec: number;
|
||||
maxOrderAmountRatio: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AutotradeValidationResult {
|
||||
isValid: boolean;
|
||||
blockedReasons: string[];
|
||||
warnings: string[];
|
||||
cashBalance: number;
|
||||
effectiveAllocationAmount: number;
|
||||
effectiveDailyLossLimit: number;
|
||||
}
|
||||
|
||||
export interface AutotradeMinuteCandle {
|
||||
time: string;
|
||||
open: number;
|
||||
high: number;
|
||||
low: number;
|
||||
close: number;
|
||||
volume: number;
|
||||
timestamp?: number;
|
||||
}
|
||||
|
||||
export interface AutotradeMinutePatternContext {
|
||||
timeframe: "1m";
|
||||
candleCount: number;
|
||||
impulseDirection: "up" | "down" | "flat";
|
||||
impulseBarCount: number;
|
||||
consolidationBarCount: number;
|
||||
impulseChangeRate?: number;
|
||||
impulseRangePercent?: number;
|
||||
consolidationRangePercent?: number;
|
||||
consolidationCloseClusterPercent?: number;
|
||||
consolidationVolumeRatio?: number;
|
||||
breakoutUpper?: number;
|
||||
breakoutLower?: number;
|
||||
}
|
||||
|
||||
export interface AutotradeBudgetContext {
|
||||
setupAllocationPercent: number;
|
||||
setupAllocationAmount: number;
|
||||
effectiveAllocationAmount: number;
|
||||
strategyMaxOrderAmountRatio: number;
|
||||
effectiveOrderBudgetAmount: number;
|
||||
estimatedBuyUnitCost: number;
|
||||
estimatedBuyableQuantity: number;
|
||||
}
|
||||
|
||||
export interface AutotradePortfolioContext {
|
||||
holdingQuantity: number;
|
||||
sellableQuantity: number;
|
||||
averagePrice: number;
|
||||
estimatedSellableNetAmount?: number;
|
||||
}
|
||||
|
||||
export interface AutotradeExecutionCostProfileSnapshot {
|
||||
buyFeeRate: number;
|
||||
sellFeeRate: number;
|
||||
sellTaxRate: number;
|
||||
}
|
||||
|
||||
export interface AutotradeSessionInfo {
|
||||
sessionId: string;
|
||||
symbol: string;
|
||||
runtimeState: "RUNNING" | "STOPPED";
|
||||
leaderTabId: string;
|
||||
startedAt: string;
|
||||
lastHeartbeatAt: string;
|
||||
endedAt: string | null;
|
||||
stopReason: AutotradeStopReason | null;
|
||||
effectiveAllocationAmount: number;
|
||||
effectiveDailyLossLimit: number;
|
||||
}
|
||||
|
||||
export interface AutotradeMarketSnapshot {
|
||||
symbol: string;
|
||||
stockName?: string;
|
||||
market?: "KOSPI" | "KOSDAQ";
|
||||
requestAtIso?: string;
|
||||
requestAtKst?: string;
|
||||
tickTime?: string;
|
||||
executionClassCode?: string;
|
||||
isExpected?: boolean;
|
||||
trId?: string;
|
||||
currentPrice: number;
|
||||
prevClose?: number;
|
||||
changeRate: number;
|
||||
open: number;
|
||||
high: number;
|
||||
low: number;
|
||||
tradeVolume: number;
|
||||
accumulatedVolume: number;
|
||||
tradeStrength?: number;
|
||||
askPrice1?: number;
|
||||
bidPrice1?: number;
|
||||
askSize1?: number;
|
||||
bidSize1?: number;
|
||||
totalAskSize?: number;
|
||||
totalBidSize?: number;
|
||||
buyExecutionCount?: number;
|
||||
sellExecutionCount?: number;
|
||||
netBuyExecutionCount?: number;
|
||||
spread?: number;
|
||||
spreadRate?: number;
|
||||
dayRangePercent?: number;
|
||||
dayRangePosition?: number;
|
||||
volumeRatio?: number;
|
||||
recentTradeCount?: number;
|
||||
recentTradeVolumeSum?: number;
|
||||
recentAverageTradeVolume?: number;
|
||||
accumulatedVolumeDelta?: number;
|
||||
netBuyExecutionDelta?: number;
|
||||
orderBookImbalance?: number;
|
||||
liquidityDepth?: number;
|
||||
topLevelOrderBookImbalance?: number;
|
||||
buySellExecutionRatio?: number;
|
||||
recentPriceHigh?: number;
|
||||
recentPriceLow?: number;
|
||||
recentPriceRangePercent?: number;
|
||||
recentTradeVolumes?: number[];
|
||||
recentNetBuyTrail?: number[];
|
||||
recentTickAgesSec?: number[];
|
||||
intradayMomentum?: number;
|
||||
recentReturns?: number[];
|
||||
recentPrices: number[];
|
||||
marketDataLatencySec?: number;
|
||||
recentMinuteCandles?: AutotradeMinuteCandle[];
|
||||
minutePatternContext?: AutotradeMinutePatternContext;
|
||||
budgetContext?: AutotradeBudgetContext;
|
||||
portfolioContext?: AutotradePortfolioContext;
|
||||
executionCostProfile?: AutotradeExecutionCostProfileSnapshot;
|
||||
}
|
||||
|
||||
export interface AutotradeProposedOrder {
|
||||
symbol: string;
|
||||
side: "buy" | "sell";
|
||||
orderType: "limit" | "market";
|
||||
price?: number;
|
||||
quantity?: number;
|
||||
}
|
||||
|
||||
export interface AutotradeSignalCandidate {
|
||||
signal: "buy" | "sell" | "hold";
|
||||
confidence: number;
|
||||
reason: string;
|
||||
ttlSec: number;
|
||||
riskFlags: string[];
|
||||
proposedOrder?: AutotradeProposedOrder;
|
||||
source: "openai" | "fallback" | "subscription_cli";
|
||||
providerVendor?: "codex" | "gemini";
|
||||
providerModel?: string;
|
||||
}
|
||||
|
||||
export interface AutotradeRuntimeLog {
|
||||
id: string;
|
||||
level: "info" | "warning" | "error";
|
||||
stage?:
|
||||
| "session"
|
||||
| "strategy_compile"
|
||||
| "strategy_validate"
|
||||
| "signal_request"
|
||||
| "signal_response"
|
||||
| "risk_gate"
|
||||
| "order_execution"
|
||||
| "order_blocked"
|
||||
| "provider_fallback"
|
||||
| "engine_error";
|
||||
message: string;
|
||||
detail?: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AutotradeCompileResponse {
|
||||
ok: boolean;
|
||||
compiledStrategy: AutotradeCompiledStrategy;
|
||||
}
|
||||
|
||||
export interface AutotradeValidateResponse {
|
||||
ok: boolean;
|
||||
validation: AutotradeValidationResult;
|
||||
}
|
||||
|
||||
export interface AutotradeSessionResponse {
|
||||
ok: boolean;
|
||||
session: AutotradeSessionInfo;
|
||||
}
|
||||
|
||||
export interface AutotradeSignalResponse {
|
||||
ok: boolean;
|
||||
signal: AutotradeSignalCandidate;
|
||||
}
|
||||
Reference in New Issue
Block a user