484 lines
18 KiB
Markdown
484 lines
18 KiB
Markdown
# 모의투자·매매 시그널 알림 처리 과정
|
||
|
||
goldenChart에서 **매매 시그널 알림**과 **모의투자(투자관리) 자동·수동 체결**이 어떻게 연결되는지, 처리 조건·흐름·관련 코드를 정리한 문서입니다.
|
||
|
||
> **핵심:** 시그널 **알림**과 모의 **체결**은 같은 전략 평가에서 출발하지만, **이후 파이프라인과 통과 조건이 다릅니다.**
|
||
> 알림이 많아도 체결이 적을 수 있는 구조가 정상 동작에 가깝습니다.
|
||
|
||
---
|
||
|
||
## 1. 개요
|
||
|
||
| 구분 | 역할 | 결과물 |
|
||
|------|------|--------|
|
||
| **시그널 발생** | 실시간 전략이 BUY/SELL 조건 충족 판정 | STOMP, `gc_trade_signal`, FCM, 프론트 알림 목록 |
|
||
| **모의 자동 체결** | 설정·예수금·포지션 규칙 통과 시 모의 계좌 주문 | `gc_paper_trade`, 원장·KPI 갱신 |
|
||
| **모의 수동 체결** | 사용자가 투자관리·차트에서 주문 | 동일 `gc_paper_*` 계좌 |
|
||
|
||
자동 체결은 **백엔드 전용**입니다. 브라우저·가상매매 화면이 꺼져 있어도 서버가 업비트 WS·봉 데이터를 받는 한, Match로 동기화된 live 설정이 있으면 평가·체결 시도가 이어집니다.
|
||
|
||
### 1.1 사용자 범위 (정식 로그인 vs 게스트)
|
||
|
||
| 구분 | 식별 | 매매·모의·전략·자동매매 |
|
||
|------|------|------------------------|
|
||
| **정식 로그인** | `X-User-Id` (회원 ID) | **지원** — 모의 계좌·설정·live 설정·체결 모두 `user_id` 단일 기준 (기기 무관) |
|
||
| **게스트 입장** | `X-Device-Id`만 (비로그인) | **미지원** — API 403, 프론트 `FormalLoginGate`·로그인 유도 |
|
||
|
||
- 모의 계좌: `gc_paper_account`는 `findByUserId` 1계좌, `device_id`는 `user:{userId}` 합성 키(UK용).
|
||
- 시그널·주문 큐: `gc_live_strategy_settings.user_id IS NOT NULL` 인 행만 평가·`OrderExecutionQueue` 적재.
|
||
- 마이그레이션 `V54`: 기존 거래·시그널 데이터 초기화, device-only live 체크 OFF.
|
||
|
||
---
|
||
|
||
## 2. 전체 아키텍처
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph ingest [시세·봉]
|
||
WS[업비트 WebSocket 틱]
|
||
BB[BarBuilder 1m 확정·상위봉 전파]
|
||
TS[Ta4jStorage]
|
||
WS --> BB --> TS
|
||
end
|
||
|
||
subgraph eval [전략 평가]
|
||
BCE[BarCloseStrategyEvaluationService]
|
||
LSS[LiveStrategyScheduler 3초]
|
||
LSE[LiveStrategyEvaluator]
|
||
TS --> BCE
|
||
TS --> LSS
|
||
BCE --> LSE
|
||
LSS --> LSE
|
||
end
|
||
|
||
subgraph signal_out [시그널 산출 - 알림 경로]
|
||
STOMP[TradingWebSocketBroker STOMP]
|
||
TSS[TradeSignalService.save]
|
||
FCM[FcmPushService]
|
||
LSE -->|BUY/SELL| BCE
|
||
LSE -->|BUY/SELL| LSS
|
||
BCE --> STOMP
|
||
BCE --> TSS
|
||
LSS --> STOMP
|
||
LSS --> TSS
|
||
TSS --> FCM
|
||
end
|
||
|
||
subgraph order_path [주문 경로 - 체결]
|
||
OEQ[OrderExecutionQueue]
|
||
TES[TradingExecutionService]
|
||
PTS[PaperTradingService.tryExecuteOnSignal]
|
||
BCE -->|deviceId != null| OEQ
|
||
LSS -->|deviceId != null| OEQ
|
||
OEQ --> TES
|
||
TES --> PTS
|
||
end
|
||
|
||
subgraph fe [프론트]
|
||
LSN[LiveSignalNotifier / STOMP]
|
||
TNC[TradeNotificationContext]
|
||
PTP[PaperTradingPage / TradeOrderPanel]
|
||
STOMP --> LSN --> TNC
|
||
PTS --> PTP
|
||
end
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 사전 설정 (DB·앱)
|
||
|
||
### 3.1 종목별 실시간 전략 — `gc_live_strategy_settings`
|
||
|
||
| 필드 | 설명 |
|
||
|------|------|
|
||
| `market` | 종목 코드 (예: `KRW-BTC`) |
|
||
| `user_id` / `device_id` | **회원:** `user_id`만 저장, `device_id=null` · **비회원:** `device_id`만 |
|
||
| `strategy_id` | 사용할 `GcStrategy` |
|
||
| `is_live_check` | 실시간 체크 ON → 평가·시그널 대상 |
|
||
| `execution_type` | `CANDLE_CLOSE`(봉 마감) 또는 `REALTIME_TICK`(3초 틱) |
|
||
| `position_mode` | `LONG_ONLY`(포지션 추적) 또는 `SIGNAL_ONLY`(규칙만) |
|
||
| `candle_type` | UI 기본 분봉; 실제 평가 분봉은 DSL `StrategyConditionTimeframeService` 기준 |
|
||
|
||
**저장 API:** `PUT /api/strategy/settings` (`LiveStrategySettingsService`)
|
||
|
||
- 가상투자 Match 시 `syncVirtualTargetsToBackend()` → 종목별 `isLiveCheck=true` 일괄 반영 (`frontend/src/utils/virtualLiveStrategySync.ts`)
|
||
- 차트·설정의 전역 실시간 체크는 `gc_app_settings.live_strategy_check` / `live_strategy_id` 와 연동
|
||
|
||
### 3.2 모의투자·실행 모드 — `gc_app_settings`
|
||
|
||
| 필드 | 자동 체결 관련 |
|
||
|------|----------------|
|
||
| `paper_trading_enabled` | 모의투자 마스터 ON |
|
||
| `paper_auto_trade_enabled` | **전략 시그널 → 모의 자동 체결** ON |
|
||
| `paper_auto_trade_budget_pct` | 자동 매수 시 가용 현금 대비 사용 비율 (기본 95%) |
|
||
| `paper_initial_capital` | 초기 자본 |
|
||
| `paper_fee_rate_pct` / `paper_slippage_pct` | 수수료·슬리피지 |
|
||
| `paper_min_order_krw` | 최소 주문 금액 (기본 5,000원) |
|
||
| `trading_mode` | `PAPER` / `LIVE` / `BOTH` — 자동 체결 대상 분기 |
|
||
| `live_strategy_check` | 전역 실시간 체크 (종목별 `is_live_check` 없을 때 보조 조건) |
|
||
|
||
**조회·저장:** `GET/POST /api/app-settings` (`X-Device-Id`, 로그인 시 `X-User-Id`)
|
||
|
||
### 3.3 모의 계좌 — `gc_paper_account`
|
||
|
||
- **키:** `device_id` (HTTP `X-Device-Id`; 없으면 `anonymous`)
|
||
- 로그인 사용자도 요청 헤더의 `device_id`로 계좌를 구분 ( `user_id`는 부가 정보)
|
||
- 보유: `gc_paper_position`, 체결: `gc_paper_trade`, 한도: `gc_paper_symbol_allocation`
|
||
|
||
---
|
||
|
||
## 4. 시그널 발생 상세
|
||
|
||
### 4.1 데이터·구독 전제
|
||
|
||
1. `LiveStrategyStartupRunner` — 기동 시 `is_live_check=true` 종목 WS·Ta4j 고정 구독
|
||
2. `BarBuilder.onTick` — 1m 확정 후 상위 분봉(5m 등) 전파
|
||
3. `StrategyConditionTimeframeService` — 전략 DSL에 포함된 분봉만 평가
|
||
|
||
### 4.2 방식 A — 봉 마감 (`CANDLE_CLOSE`)
|
||
|
||
**트리거:** `BarBuilder.commitBar()` → `BarCloseStrategyEvaluationService.onMaturedBarClose()`
|
||
|
||
**진입 조건 (종목·설정 행마다):**
|
||
|
||
1. `is_live_check = true` 이고 `strategy_id` 존재
|
||
2. `execution_type = CANDLE_CLOSE` (또는 마감 시 `evaluateRealtimeAtClose` 보조)
|
||
3. `usesTimeframe(strategyId, candleType)` — DSL에 해당 분봉 포함
|
||
4. 동일 `market:candleType:barEndEpoch` **중복 평가 방지** (`evaluatedBarCloseKeys`)
|
||
|
||
**평가:** `LiveStrategyEvaluator.evaluateSettingOnCandleClose()` — **확정된 직전 봉 인덱스**에서 1회
|
||
|
||
### 4.3 방식 B — 실시간 틱 (`REALTIME_TICK`)
|
||
|
||
**트리거:** `LiveStrategyScheduler` — **3초 `fixedDelay`** (`@Scheduled`)
|
||
|
||
**조건:** `findAllByIsLiveCheckTrue()` 중 `execution_type = REALTIME_TICK`
|
||
|
||
**평가:** `evaluateSettingRealtimeTick()` — **진행 중 봉** `series.getEndIndex()`
|
||
동일 `(market, candleType, index)` 중복 시그널 방지
|
||
|
||
### 4.4 시그널 판정 (`LiveStrategyEvaluator` + `StrategySignalDeterminer`)
|
||
|
||
| `position_mode` | BUY | SELL |
|
||
|-----------------|-----|------|
|
||
| **LONG_ONLY** | 진입 규칙 + 가상 `TradingRecord` 미보유 | 청산 규칙 + 보유 중 |
|
||
| **SIGNAL_ONLY** | `entryRule` 충족 | `exitRule` 충족 |
|
||
|
||
`LONG_ONLY`에서 이미 보유인데 BUY, 무포지션인데 SELL이면 evaluator 내부에서 **`NONE`으로 정리**할 수 있음 (캐시된 포지션 상태 기준).
|
||
|
||
결과: `"BUY"` | `"SELL"` | `"NONE"`
|
||
|
||
---
|
||
|
||
## 5. 시그널 후처리 (알림 파이프라인)
|
||
|
||
BUY/SELL이 확정되면 **설정 행(`GcLiveStrategySettings`)마다** 아래가 순서대로 실행됩니다.
|
||
|
||
### 5.1 STOMP 실시간 푸시
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| 토픽 | `/sub/charts/{market}/{candleType}` |
|
||
| 페이로드 | `CandleBarDto` — OHLCV + `signal`, `strategyId`, `userId`, `deviceId`, `executionType` |
|
||
| 발행 | `TradingWebSocketBroker.publish()` |
|
||
|
||
### 5.2 DB 이력 저장
|
||
|
||
`TradeSignalService.save(deviceId, userId, market, strategyId, …)` → **`gc_trade_signal`**
|
||
|
||
- **로그인:** `user_id` 저장, `device_id`는 null일 수 있음
|
||
- **비회원:** `device_id` 저장
|
||
|
||
**API:** `GET /api/trade-signals` — 로그인 시 `user_id`, 비로그인 시 `device_id` 기준 목록
|
||
|
||
### 5.3 FCM 푸시 (선택)
|
||
|
||
`FcmPushService.sendTradeSignalIfEnabled()` — 앱 알림 설정·토큰 등록 시
|
||
로그인 사용자는 **userId** 기준 발송 (deviceId null 허용)
|
||
|
||
### 5.4 주문 큐 적재 (자동 체결 **시도**만)
|
||
|
||
```java
|
||
// BarCloseStrategyEvaluationService, LiveStrategyScheduler 공통
|
||
if (s.getDeviceId() != null) {
|
||
orderExecutionQueue.submitSignal(
|
||
s.getDeviceId(), s.getUserId(), market,
|
||
s.getStrategyId(), signal, price);
|
||
}
|
||
```
|
||
|
||
> **주문 큐:** `user_id`가 있는 live 설정만 `OrderExecutionQueue`에 적재합니다. (게스트 device-only 설정은 평가 대상에서 제외)
|
||
|
||
---
|
||
|
||
## 6. 프론트 — 매매 시그널 알림
|
||
|
||
### 6.1 STOMP 수신
|
||
|
||
| 컴포넌트 | 역할 |
|
||
|----------|------|
|
||
| `useLiveStrategyMarkers` | `/sub/charts/...` 구독, `signal` 필드 처리 |
|
||
| `signalBelongsToCurrentSession` | `userId` 또는 `deviceId` 소유자 필터 (`tradeSignalOwnership.ts`) |
|
||
| `LiveSignalNotifier` | `App.tsx` 전역, `monitoredMarkets` 대상 |
|
||
|
||
**구독 대상 (`monitoredMarkets`):**
|
||
|
||
- 가상투자 실행 중 → 가상투자 대상 종목
|
||
- 아니면 → `liveStrategyCheck` + `liveStrategyId` + 관심종목
|
||
|
||
### 6.2 알림 Context
|
||
|
||
`TradeNotificationContext`:
|
||
|
||
- STOMP 수신 → `addNotification()` (미확인 배지·토스트·사운드)
|
||
- 20초마다 `loadTradeSignals()` → 서버 이력과 병합
|
||
- 알림 ID: `{market}:{candleTime}:{signalType}`
|
||
- **알림 목록 화면:** `TradeNotificationListPage` (메뉴 알림목록)
|
||
|
||
### 6.3 알림 vs 체결 (프론트)
|
||
|
||
- 프론트는 시그널 수신 시 **`placePaperOrder`를 호출하지 않음** (과거 STOMP→주문 훅 제거됨)
|
||
- 투자관리·가상매매 UI는 **모니터링·수동 주문·설정**; 자동 체결은 백엔드만
|
||
|
||
---
|
||
|
||
## 7. 모의 자동매매 실행 파이프라인
|
||
|
||
### 7.1 주문 큐
|
||
|
||
`OrderExecutionQueue` — 단일 워커 스레드 + `RateLimiter` (업비트 429 완화)
|
||
|
||
| 단계 | 동작 |
|
||
|------|------|
|
||
| `submitSignal` | `OrderRequest.strategySignal` 큐 적재 |
|
||
| `executeNow` | `deviceId` blank면 **즉시 return** |
|
||
| 실행 | `TradingExecutionService.executeSignal()` |
|
||
|
||
### 7.2 실행 대상 분기 — `TradingExecutionService`
|
||
|
||
```text
|
||
trading_mode:
|
||
PAPER → paperTradingService.tryExecuteOnSignal (paper_trading_enabled 시)
|
||
LIVE → liveTradingService.tryExecuteOnSignal
|
||
BOTH → 둘 다 시도
|
||
```
|
||
|
||
### 7.3 모의 체결 본체 — `PaperTradingService.tryExecuteOnSignal`
|
||
|
||
**진입 전 필수 (하나라도 실패 시 return, 예외는 warn 로그):**
|
||
|
||
| # | 조건 |
|
||
|---|------|
|
||
| 1 | `deviceId` not blank |
|
||
| 2 | `signalType` ∈ {BUY, SELL} |
|
||
| 3 | `paper_trading_enabled = true` |
|
||
| 4 | `paper_auto_trade_enabled = true` |
|
||
| 5 | `live_strategy_check = true` **OR** 해당 `market`에 `is_live_check=true` 설정 존재 |
|
||
| 6 | `trading_mode`가 PAPER 또는 BOTH (`TradingExecutionService` 단계) |
|
||
|
||
**포지션 모드 `LONG_ONLY` (실제 계좌 보유 기준):**
|
||
|
||
| 시그널 | 스킵 조건 |
|
||
|--------|-----------|
|
||
| BUY | 해당 종목 **이미 보유** (`quantity > 0`) |
|
||
| SELL | 해당 종목 **미보유** |
|
||
|
||
**매수 금액 계산:**
|
||
|
||
```text
|
||
budget = (cash_balance - reserved_cash) × paper_auto_trade_budget_pct / 100
|
||
execPrice = price × (1 + slippage%)
|
||
qty = budget / (execPrice × (1 + fee%))
|
||
```
|
||
|
||
| # | 매수 스킵 |
|
||
|---|-----------|
|
||
| 7 | `budget < paper_min_order_krw` |
|
||
| 8 | `qty × execPrice < min_order` |
|
||
|
||
**매도:** 보유 수량 전량(가용 수량, 미체결 매도 예약 제외)
|
||
|
||
**체결:** `executeTrade(..., source="STRATEGY", autoTrade=true)`
|
||
|
||
- 종목 한도: `PaperAllocationService.validateBuy` — `getOrDefault`로 한도 행 없으면 초기자본 규모 한도 자동 생성
|
||
- 체결 기록: `gc_paper_trade`, 원장: `PaperLedgerService`
|
||
|
||
---
|
||
|
||
## 8. 모의 수동매매 (시그널과 별도)
|
||
|
||
**경로:** `TradeOrderPanel` → `POST /api/paper/orders` → `PaperTradingService.placeOrder`
|
||
|
||
| 구분 | 자동 (`tryExecuteOnSignal`) | 수동 (`placeOrder`) |
|
||
|------|----------------------------|---------------------|
|
||
| `paper_auto_trade_enabled` | 필수 ON | 불필요 |
|
||
| 예산 | 전역 `paper_auto_trade_budget_pct` | 요청 수량·금액·한도 |
|
||
| `source` | `STRATEGY` | `MANUAL` 등 |
|
||
| 한도 검증 | `autoTrade=true` | `autoTrade=false` |
|
||
|
||
수동 주문도 `paper_trading_enabled` 및 동일 계좌·한도 규칙을 따릅니다.
|
||
|
||
---
|
||
|
||
## 9. 가상투자 ↔ 백엔드 동기화
|
||
|
||
가상투자 **Match(실행)** 시:
|
||
|
||
1. `syncVirtualTargetsToBackend(targets, session, isLiveCheck=true)`
|
||
2. 종목별 `saveLiveStrategySettings` — `isLiveCheck`, `executionType`, `positionMode`
|
||
3. `putPaperAllocationsBulk` — 종목별 한도 행(베스트 에포트)
|
||
4. 전략 분봉 pin — `pinStrategyEvaluationTimeframes`
|
||
|
||
**중지 시:** `stopVirtualLiveOnBackend` — `isLiveCheck=false`
|
||
|
||
서버는 이후 **BarClose / LiveStrategyScheduler**만으로 평가·시그널·(조건 충족 시) 체결을 진행합니다.
|
||
|
||
---
|
||
|
||
## 10. 처리 조건 요약표
|
||
|
||
### 10.1 시그널 알림이 쌓이려면
|
||
|
||
| 조건 | 필수 |
|
||
|------|:----:|
|
||
| `gc_live_strategy_settings.is_live_check = true` | ✓ |
|
||
| `strategy_id` 지정 | ✓ |
|
||
| DSL에 해당 `candle_type` 포함 | ✓ |
|
||
| Ta4jStorage에 봉 데이터 존재 | ✓ |
|
||
| 전략 규칙 BUY/SELL 판정 | ✓ |
|
||
|
||
→ **DB 저장·STOMP·(설정 시) FCM·프론트 알림** (deviceId 없어도 가능)
|
||
|
||
### 10.2 모의 자동 체결이 되려면
|
||
|
||
위 시그널 조건 **+** 아래 **전부** (실무상):
|
||
|
||
| 조건 | 필수 |
|
||
|------|:----:|
|
||
| live 설정 `user_id != null` (주문 큐 진입) | ✓ |
|
||
| `paper_trading_enabled` | ✓ |
|
||
| `paper_auto_trade_enabled` | ✓ |
|
||
| `trading_mode` ∈ {PAPER, BOTH} | ✓ |
|
||
| `live_strategy_check` OR 종목 `is_live_check` | ✓ |
|
||
| LONG_ONLY: BUY=미보유, SELL=보유 | ✓ |
|
||
| 예수금·한도·최소주문금액 | ✓ |
|
||
|
||
---
|
||
|
||
## 11. 알림은 많은데 체결이 적은 대표 사례
|
||
|
||
| 현상 | 원인 |
|
||
|------|------|
|
||
| 미확인 알림 수백 건, 체결 3건 | 종목 다수 × 5분봉 × 매수·매도 시그널; 체결은 예수금·포지션 규칙으로 소수만 통과 |
|
||
| 연속 매수 알림, 체결 없음 | **예수금 소진** — 자동 매수가 남은 현금의 95%씩 사용 (1천만 → 약 3종목 후 5천원 미만) |
|
||
| 매도 알림만 많음 | **LONG_ONLY** + 미보유 → 매도 시그널은 알림만, 체결 스킵 |
|
||
| 같은 종목 매수 알림 반복 | 이미 보유 → BUY 체결 스킵 (알림은 evaluator/DB 경로에 따라 발생 가능) |
|
||
| 게스트 입장 | 매매 API 403, STOMP 시그널 구독 없음 |
|
||
| KPI 1천만, 거래 탭 과거 3건 | **계좌 초기화** 후 현금 복구, **체결 이력은 유지** |
|
||
| 자동매매 OFF | `paper_auto_trade_enabled=false` — 수동만 가능 |
|
||
|
||
**예수금 소진 예 (초기 1천만, budget 95%):**
|
||
|
||
1. 1차 매수 ≈ 950만 → 잔액 ≈ 50만
|
||
2. 2차 ≈ 47.5만 → 잔액 ≈ 2.5만
|
||
3. 3차 ≈ 2.4만 → 잔액 ≈ 1천원대 → 이후 BUY 시그널 전부 `budget < min_order` 스킵
|
||
|
||
---
|
||
|
||
## 12. 엔드투엔드 시퀀스 (봉 마감 + 자동 모의)
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant UB as 업비트 WS
|
||
participant BB as BarBuilder
|
||
participant BCE as BarCloseEval
|
||
participant LSE as LiveStrategyEvaluator
|
||
participant TSS as TradeSignalService
|
||
participant OEQ as OrderExecutionQueue
|
||
participant PTS as PaperTradingService
|
||
participant FE as 프론트 STOMP
|
||
|
||
UB->>BB: tick
|
||
BB->>BCE: onMaturedBarClose (5m 등)
|
||
BCE->>LSE: evaluateSettingOnCandleClose
|
||
LSE-->>BCE: BUY|SELL|NONE
|
||
alt BUY or SELL
|
||
BCE->>FE: STOMP CandleBarDto.signal
|
||
BCE->>TSS: save → gc_trade_signal
|
||
alt setting.deviceId != null
|
||
BCE->>OEQ: submitSignal
|
||
OEQ->>PTS: tryExecuteOnSignal
|
||
alt 모든 체결 조건 통과
|
||
PTS->>PTS: executeTrade STRATEGY
|
||
else 조건 실패
|
||
PTS-->>PTS: silent return
|
||
end
|
||
end
|
||
end
|
||
```
|
||
|
||
---
|
||
|
||
## 13. 주요 클래스·파일
|
||
|
||
### 백엔드
|
||
|
||
| 영역 | 클래스 |
|
||
|------|--------|
|
||
| 봉·마감 평가 | `BarBuilder`, `BarCloseStrategyEvaluationService` |
|
||
| 틱 평가 | `LiveStrategyScheduler` |
|
||
| 전략 판정 | `LiveStrategyEvaluator`, `StrategySignalDeterminer` |
|
||
| 시그널 저장 | `TradeSignalService`, `GcTradeSignal` |
|
||
| STOMP | `TradingWebSocketBroker` |
|
||
| 주문 큐 | `OrderExecutionQueue`, `OrderRequest` |
|
||
| 실행 분기 | `TradingExecutionService`, `TradingMode` |
|
||
| 모의 체결 | `PaperTradingService`, `PaperAllocationService` |
|
||
| Live 설정 | `LiveStrategySettingsService`, `GcLiveStrategySettings` |
|
||
| 설정 | `AppSettingsService`, `GcAppSettings` |
|
||
|
||
### 프론트
|
||
|
||
| 영역 | 파일 |
|
||
|------|------|
|
||
| 전역 STOMP 알림 | `LiveSignalNotifier.tsx`, `useLiveStrategyMarkers.ts` |
|
||
| 알림 상태 | `TradeNotificationContext.tsx`, `TradeNotificationListPage.tsx` |
|
||
| 소유자 필터 | `tradeSignalOwnership.ts` |
|
||
| 투자관리 UI | `PaperTradingPage.tsx`, `TradeOrderPanel.tsx` |
|
||
| 가상 동기화 | `virtualLiveStrategySync.ts` |
|
||
| API | `backendApi.ts` — `loadTradeSignals`, paper APIs |
|
||
|
||
### DB (핵심 테이블)
|
||
|
||
| 테이블 | 용도 |
|
||
|--------|------|
|
||
| `gc_live_strategy_settings` | 종목별 실시간 전략·체크 ON |
|
||
| `gc_trade_signal` | 매매 시그널 알림 이력 |
|
||
| `gc_app_settings` | 모의·자동매매·실행모드 전역 |
|
||
| `gc_paper_account` | 모의 계좌 (device_id) |
|
||
| `gc_paper_trade` | 체결 내역 |
|
||
| `gc_paper_symbol_allocation` | 종목별 투자 한도 |
|
||
|
||
---
|
||
|
||
## 14. 운영·디버깅 체크리스트
|
||
|
||
1. **설정 → 모의투자:** 활성화 ON, 자동매매 ON, 실행 대상 PAPER/BOTH
|
||
2. **가상투자 Match:** 대상 종목 `isLiveCheck` 백엔드 반영 여부
|
||
3. **예수금:** 투자관리 KPI `주문가능`, 체결 후 `cash_after`
|
||
4. **포지션:** LONG_ONLY 시 매도 알림 vs 실제 보유
|
||
5. **로그인:** `device_id` null 이슈 — 자동 체결 기대 시 비회원 테스트 또는 백엔드 보완 여부 확인
|
||
6. **로그 키워드:** `[TradeSignal] saved`, `[Paper] STRATEGY BUY`, `[Paper] auto trade failed`, `[OrderExecutionQueue]`
|
||
|
||
---
|
||
|
||
## 15. 관련 문서
|
||
|
||
- [전략편집기 로직 및 동작흐름.md](./전략편집기%20로직%20및%20동작흐름.md) — §9 시그널 감지, §10 시그널 발행
|
||
- [docs/모의투자_투자금_관리_설계.md](./docs/모의투자_투자금_관리_설계.md) — 계좌·한도·원장 설계
|
||
- [backend/FCM_BACKEND.md](./backend/FCM_BACKEND.md) — 푸시 연동
|
||
- [db_struct.md](./db_struct.md) — 테이블 상세
|
||
|
||
---
|
||
|
||
*문서 기준: goldenChart 저장소 백엔드·프론트 구현 (자동 체결 백엔드 전용, 회원 live 설정 `device_id=null` 주문 큐 분기 포함).*
|