RSI, MACD, EMA 크로스오버 세 지표를 조합한 복합 모멘텀 전략을 구현합니다. 2개 이상 일치할 때만 진입하며 한국 시장 파라미터를 사용합니다.
모멘텀 전략 개요
모멘텀 전략은 가격의 추세와 속도를 측정하여 상승 추세에 매수, 하락 추세에 매도하는 방법입니다. 최근 수익률이 높은 자산이 단기적으로 추가 상승하는 시장의 관성을 활용합니다.
이 전략은 RSI, MACD, 이동평균 교차 세 가지 기술 지표를 조합합니다. 단일 지표보다 노이즈에 강건한 매매 신호를 만들 수 있습니다.
| 지표 | 역할 | 측정 대상 |
|---|---|---|
| EMA 크로스오버 | 추세 방향 판단 | 이동평균 교차 |
| RSI | 과매수/과매도 판단 | 가격 변동의 속도와 크기 |
| MACD | 추세 강도와 전환 판단 | 이동평균 수렴/발산 |
단일 지표만으로는 거짓 신호가 빈번합니다. 2개 이상의 지표가 동일 방향을 가리킬 때만 진입하는 것이 핵심입니다.
의존성
# pyproject.toml
[project.dependencies]
ta = ">=0.11" # 기술 분석 라이브러리
pandas = ">=2.0"
numpy = ">=1.24"import pandas as pd
import numpy as np
from ta.trend import EMAIndicator, MACD as MACDIndicator
from ta.momentum import RSIIndicator지표 계산은 ta 라이브러리에 위임합니다. EMAIndicator는 지수이동평균, RSIIndicator는 RSI, MACDIndicator는 MACD 선과 시그널 선을 계산합니다.
EMA 골든크로스 / 데드크로스
이동평균 크로스오버란
이동평균 크로스오버는 대표적인 추세 추종 신호입니다. 단기 이동평균이 장기 이동평균을 상향 돌파하면 골든크로스, 하향 돌파하면 데드크로스입니다.
| 패턴 | 조건 | 의미 |
|---|---|---|
| 골든크로스 | 단기 MA가 장기 MA를 상향 돌파 | 강세 전환 - 매수 신호 |
| 데드크로스 | 단기 MA가 장기 MA를 하향 돌파 | 약세 전환 - 매도 신호 |
SMA vs EMA
단순이동평균(Simple Moving Average, SMA)은 모든 데이터에 동일한 가중치를 부여합니다. 반면 **지수이동평균(Exponential Moving Average, EMA)**은 최근 데이터에 더 높은 가중치를 부여합니다. 변동성이 큰 한국 시장에서는 EMA가 더 빠르게 추세 변화에 반응합니다.
graph LR
A[가격 데이터] --> B[EMA 단기]
A --> C[EMA 장기]
B --> D{단기 > 장기?}
C --> D
D -->|상향 교차| E[골든크로스 - 매수]
D -->|하향 교차| F[데드크로스 - 매도]
D -->|변화 없음| G[중립]
일반적인 MA 조합
| 조합 | 단기 | 장기 | 특성 |
|---|---|---|---|
| 빠른 크로스 | 5일 | 20일 | 민감, 거짓 신호 많음 |
| 표준 크로스 | 20일 | 60일 | 중단기 추세 |
| 클래식 크로스 | 50일 | 200일 | 장기 추세, 신뢰도 높음 |
한국 시장 예시 설정
아래 기간은 전략 동작을 설명하기 위한 시작값입니다. 종목과 검증 기간에 따라 결과가 달라지므로 시장별 우위를 뜻하지 않습니다.
- 코스피 대형주: 20일/60일 EMA (변동성 보통)
- 코스닥 중소형주: 10일/30일 EMA (변동성 높음)
Python 구현
def ma_crossover_signals(
df: pd.DataFrame,
fast: int = 20,
slow: int = 60,
) -> pd.DataFrame:
"""이동평균 크로스오버 신호 생성.
Args:
df: OHLCV(시가/고가/저가/종가/거래량) DataFrame (columns: open, high, low, close, volume)
fast: 단기 이동평균 기간
slow: 장기 이동평균 기간
Returns:
signal 컬럼이 추가된 DataFrame (1=매수, -1=매도, 0=중립)
"""
df = df.copy()
# EMA 계산
df["ema_fast"] = EMAIndicator(
close=df["close"], window=fast
).ema_indicator()
df["ema_slow"] = EMAIndicator(
close=df["close"], window=slow
).ema_indicator()
# 크로스오버 감지
df["ma_cross"] = 0
# 골든크로스: fast가 slow 위로 교차
df.loc[
(df["ema_fast"] > df["ema_slow"])
& (df["ema_fast"].shift(1) <= df["ema_slow"].shift(1)),
"ma_cross",
] = 1
# 데드크로스: fast가 slow 아래로 교차
df.loc[
(df["ema_fast"] < df["ema_slow"])
& (df["ema_fast"].shift(1) >= df["ema_slow"].shift(1)),
"ma_cross",
] = -1
return df교차 감지의 핵심은 현재 봉과 직전 봉의 상대적 위치 변화입니다.
- 골든크로스: 직전 봉에서
fast <= slow이고, 현재 봉에서fast > slow - 데드크로스: 직전 봉에서
fast >= slow이고, 현재 봉에서fast < slow
RSI (Relative Strength Index)
RSI 개요
RSI는 가격 변동의 속도와 크기를 측정하여 0~100 사이의 값을 반환하는 오실레이터입니다. 특정 기간 동안의 상승폭 평균과 하락폭 평균의 비율로 계산합니다.
계산 공식
RSI가 높으면 상승 압력이 강했다는 의미이고, 낮으면 하락 압력이 강했다는 의미입니다.
신호 해석
| RSI 범위 | 상태 | 행동 |
|---|---|---|
| 과매수 (Overbought) | 매도 고려 | |
| 과매도 (Oversold) | 매수 고려 | |
| 중립 | 다른 지표 참조 |
RSI가 과매수·과매도 영역에 진입했다고 바로 매매하지는 않습니다. 포착해야 할 시점은 해당 영역을 벗어나는 순간입니다.
- 매수 시점: RSI가 과매도 영역(30 이하)에서 위로 돌파할 때
- 매도 시점: RSI가 과매수 영역(70 이상)에서 아래로 돌파할 때
한국 시장 파라미터
| 조건 | RSI 기간 | 과매수 | 과매도 | 비고 |
|---|---|---|---|---|
| 추세장 (상승/하락 뚜렷) | 14 | 80 | 20 | 추세 따라가기 |
| 박스권 (횡보) | 14 | 70 | 30 | 표준 설정 |
| 단기 매매 | 7 | 70 | 30 | 민감하게 반응 |
| 코스닥 중소형 | 9 | 75 | 25 | 변동성 보정 |
추세장에서는 과매수/과매도 기준을 80/20으로 넓히면 추세를 더 오래 따라갈 수 있습니다. 박스권에서는 표준 70/30이 효과적입니다.
RSI 다이버전스
다이버전스는 가격과 RSI의 방향이 반대로 움직이는 현상이며 추세 전환 가능성을 살피는 보조 신호입니다.
| 유형 | 가격 | RSI | 의미 |
|---|---|---|---|
| 강세 다이버전스 | 저점 갱신 | 저점 상승 | 하락 추세 약화 - 반등 가능 |
| 약세 다이버전스 | 고점 갱신 | 고점 하락 | 상승 추세 약화 - 하락 가능 |
graph TB
subgraph 강세다이버전스["강세 다이버전스"]
P1["가격: 저점 하락"] --> S1["RSI: 저점 상승"]
S1 --> R1["반등 신호"]
end
subgraph 약세다이버전스["약세 다이버전스"]
P2["가격: 고점 상승"] --> S2["RSI: 고점 하락"]
S2 --> R2["하락 신호"]
end
Python 구현
def rsi_signals(
df: pd.DataFrame,
window: int = 14,
overbought: float = 70,
oversold: float = 30,
) -> pd.DataFrame:
"""RSI 기반 매매 신호 생성.
Args:
df: OHLCV DataFrame
window: RSI 계산 기간
overbought: 과매수 기준
oversold: 과매도 기준
Returns:
rsi, rsi_signal 컬럼이 추가된 DataFrame
"""
df = df.copy()
df["rsi"] = RSIIndicator(
close=df["close"], window=window
).rsi()
df["rsi_signal"] = 0
# 과매도 탈출 → 매수 (RSI가 oversold 아래에서 위로)
df.loc[
(df["rsi"] > oversold)
& (df["rsi"].shift(1) <= oversold),
"rsi_signal",
] = 1
# 과매수 이탈 → 매도 (RSI가 overbought 위에서 아래로)
df.loc[
(df["rsi"] < overbought)
& (df["rsi"].shift(1) >= overbought),
"rsi_signal",
] = -1
return dfMACD (Moving Average Convergence Divergence)
MACD 구성 요소
MACD는 세 가지 요소로 구성됩니다.
| 요소 | 계산 | 기본값 |
|---|---|---|
| MACD 선 | EMA(fast) - EMA(slow) | EMA(12) - EMA(26) |
| Signal 선 | EMA(MACD, signal) | EMA(MACD, 9) |
| 히스토그램 | MACD - Signal | - |
MACD 선은 두 EMA의 차이를 나타내고, Signal 선은 MACD의 이동평균입니다. 히스토그램은 이 둘의 거리를 시각화한 것입니다.
신호 해석
| 패턴 | 조건 | 의미 |
|---|---|---|
| MACD 골든크로스 | MACD가 Signal 위로 교차 | 매수 신호 |
| MACD 데드크로스 | MACD가 Signal 아래로 교차 | 매도 신호 |
| 0선 돌파 | MACD가 0 위로 돌파 | 상승 추세 확인 |
| 히스토그램 확대 | 히스토그램 양봉 증가 | 추세 강화 |
히스토그램 해석
히스토그램은 추세의 강도 변화를 가장 민감하게 반영합니다.
- 양봉 증가: MACD가 Signal에서 멀어짐 - 상승 추세 강화
- 양봉 감소: MACD가 Signal에 수렴 - 상승 추세 약화 (데드크로스 임박)
- 음봉 증가: 하락 추세 강화
- 음봉 감소: 하락 추세 약화 (골든크로스 임박)
graph TD
A["MACD 히스토그램"] --> B{양봉/음봉?}
B -->|양봉| C{증가/감소?}
B -->|음봉| D{증가/감소?}
C -->|증가| E["상승 추세 강화"]
C -->|감소| F["상승 추세 약화<br/>데드크로스 임박"]
D -->|증가 -방향| G["하락 추세 강화"]
D -->|감소 -방향| H["하락 추세 약화<br/>골든크로스 임박"]
한국 시장 파라미터
| 시장 | fast | slow | signal | 비고 |
|---|---|---|---|---|
| 코스피 대형주 | 12 | 26 | 9 | 표준 설정 |
| 코스닥 | 8 | 21 | 5 | 빠른 반응 |
| 일봉 단기 | 6 | 13 | 5 | 스윙 트레이딩 |
코스닥 종목은 변동성이 크므로 표준 (12, 26, 9) 대신 **(8, 21, 5)**로 설정해 빠르게 반응하도록 조정합니다.
Python 구현
def macd_signals(
df: pd.DataFrame,
fast: int = 12,
slow: int = 26,
signal: int = 9,
) -> pd.DataFrame:
"""MACD 크로스오버 신호 생성.
Args:
df: OHLCV DataFrame
fast: 단기 EMA 기간
slow: 장기 EMA 기간
signal: 시그널 EMA 기간
Returns:
macd, macd_signal_line, macd_hist, macd_signal 컬럼 추가
"""
df = df.copy()
macd = MACDIndicator(
close=df["close"],
window_fast=fast,
window_slow=slow,
window_sign=signal,
)
df["macd"] = macd.macd()
df["macd_signal_line"] = macd.macd_signal()
df["macd_hist"] = macd.macd_diff()
df["macd_signal"] = 0
# MACD 골든크로스
df.loc[
(df["macd"] > df["macd_signal_line"])
& (df["macd"].shift(1) <= df["macd_signal_line"].shift(1)),
"macd_signal",
] = 1
# MACD 데드크로스
df.loc[
(df["macd"] < df["macd_signal_line"])
& (df["macd"].shift(1) >= df["macd_signal_line"].shift(1)),
"macd_signal",
] = -1
return df복합 모멘텀 신호
전략 로직
단일 지표의 한계를 극복하기 위해, 2개 이상의 지표가 동일 방향을 가리킬 때만 진입합니다.
| 강세 표 조건 | 약세 표 조건 |
|---|---|
| MA 골든크로스 또는 fast > slow | MA 데드크로스 또는 fast < slow |
| 50 < RSI < 과매수 기준 | 과매도 기준 < RSI < 50 |
| MACD 골든크로스 또는 히스토그램 양전환 | MACD 데드크로스 또는 히스토그램 음전환 |
각 지표는 강세, 약세, 중립 중 하나로 투표합니다. 같은 방향의 표가 min_confirmations 이상이면 신호를 냅니다. momentum_score는 강세 표 수에서 약세 표 수를 뺀 진단값으로 남깁니다.
Python 구현
def combined_momentum_signal(
df: pd.DataFrame,
ma_fast: int = 20,
ma_slow: int = 60,
rsi_window: int = 14,
rsi_overbought: float = 70,
rsi_oversold: float = 30,
macd_fast: int = 12,
macd_slow: int = 26,
macd_signal: int = 9,
min_confirmations: int = 2,
) -> pd.DataFrame:
"""복합 모멘텀 신호 생성.
min_confirmations개 이상의 지표가 동일 방향일 때만 신호 발생.
"""
df = ma_crossover_signals(df, ma_fast, ma_slow)
df = rsi_signals(df, rsi_window, rsi_overbought, rsi_oversold)
df = macd_signals(df, macd_fast, macd_slow, macd_signal)
# 강세=1, 약세=-1, 판단 불가나 극단 구간=0
df["ma_vote"] = np.select(
[df["ema_fast"] > df["ema_slow"], df["ema_fast"] < df["ema_slow"]],
[1, -1],
default=0,
)
df["rsi_vote"] = np.select(
[
(df["rsi"] > 50) & (df["rsi"] < rsi_overbought),
(df["rsi"] < 50) & (df["rsi"] > rsi_oversold),
],
[1, -1],
default=0,
)
df["macd_vote"] = np.select(
[df["macd_hist"] > 0, df["macd_hist"] < 0],
[1, -1],
default=0,
)
vote_columns = ["ma_vote", "rsi_vote", "macd_vote"]
df["bullish_confirmations"] = (df[vote_columns] == 1).sum(axis=1)
df["bearish_confirmations"] = (df[vote_columns] == -1).sum(axis=1)
df["momentum_score"] = (
df["bullish_confirmations"] - df["bearish_confirmations"]
)
df["signal"] = 0
df.loc[
df["bullish_confirmations"] >= min_confirmations, "signal"
] = 1
df.loc[
df["bearish_confirmations"] >= min_confirmations, "signal"
] = -1
return df신호 발생 예시
| 강세 표 | 약세 표 | momentum_score | min_confirmations=2 판정 |
|---|---|---|---|
| 3 | 0 | +3 | 매수 |
| 2 | 1 | +1 | 매수 |
| 1 | 1 | 0 | 신호 없음 |
| 1 | 2 | -1 | 매도 |
| 0 | 3 | -3 | 매도 |
한국 시장 예시 파라미터
세 가지 프리셋은 실행 예시이며 검증된 최적값이 아닙니다. 실제 적용 전에는 종목군과 기간을 고정하고 워크포워드 검증을 수행해야 합니다.
코스피 표준 (kospi_standard)
대형주 중심의 안정적인 트레이딩에 적합합니다.
"kospi_standard": {
"ma_fast": 20, "ma_slow": 60,
"rsi_window": 14, "rsi_overbought": 70, "rsi_oversold": 30,
"macd_fast": 12, "macd_slow": 26, "macd_signal": 9,
"min_confirmations": 2,
}코스닥 공격적 (kosdaq_aggressive)
변동성이 큰 중소형주의 가격 변화에 빠르게 대응합니다.
"kosdaq_aggressive": {
"ma_fast": 10, "ma_slow": 30,
"rsi_window": 9, "rsi_overbought": 75, "rsi_oversold": 25,
"macd_fast": 8, "macd_slow": 21, "macd_signal": 5,
"min_confirmations": 2,
}보수적 (conservative)
장기 추세를 따르며, 3개 지표가 모두 일치할 때만 진입합니다.
"conservative": {
"ma_fast": 50, "ma_slow": 200,
"rsi_window": 14, "rsi_overbought": 80, "rsi_oversold": 20,
"macd_fast": 12, "macd_slow": 26, "macd_signal": 9,
"min_confirmations": 3, # 3개 모두 일치 시만
}파라미터 비교
| 항목 | 코스피 표준 | 코스닥 공격적 | 보수적 |
|---|---|---|---|
| EMA 단기/장기 | 20/60 | 10/30 | 50/200 |
| RSI 기간 | 14 | 9 | 14 |
| RSI 과매수/과매도 | 70/30 | 75/25 | 80/20 |
| MACD (fast/slow/signal) | 12/26/9 | 8/21/5 | 12/26/9 |
| 최소 확인 수 | 2개 | 2개 | 3개 |
| 신호 빈도 | 중간 | 높음 | 낮음 |
| 거짓 신호 빈도 | 중간 | 높음 | 낮음 |
전체 파라미터 딕셔너리
MOMENTUM_PARAMS = {
"kospi_standard": {
"ma_fast": 20, "ma_slow": 60,
"rsi_window": 14, "rsi_overbought": 70, "rsi_oversold": 30,
"macd_fast": 12, "macd_slow": 26, "macd_signal": 9,
"min_confirmations": 2,
},
"kosdaq_aggressive": {
"ma_fast": 10, "ma_slow": 30,
"rsi_window": 9, "rsi_overbought": 75, "rsi_oversold": 25,
"macd_fast": 8, "macd_slow": 21, "macd_signal": 5,
"min_confirmations": 2,
},
"conservative": {
"ma_fast": 50, "ma_slow": 200,
"rsi_window": 14, "rsi_overbought": 80, "rsi_oversold": 20,
"macd_fast": 12, "macd_slow": 26, "macd_signal": 9,
"min_confirmations": 3,
},
}사용 예:
params = MOMENTUM_PARAMS["kospi_standard"]
result = combined_momentum_signal(df, **params)포지션 사이징
고정 비율 방식
1회 거래의 최대 손실을 전체 예산의 일정 비율로 제한합니다. 손절가까지의 거리에 따라 매수 수량이 결정됩니다.
def calculate_position_size(
budget: float,
price: float,
stop_loss_pct: float,
risk_per_trade_pct: float = 1.0,
) -> int:
"""고정비율 포지션 사이징.
Args:
budget: 총 투자 가능 금액
price: 현재 주가
stop_loss_pct: 손절 비율 (예: -3.0)
risk_per_trade_pct: 1회 거래 최대 손실 비율 (예산 대비, 기본 1%)
Returns:
매수 수량 (정수)
"""
max_loss_amount = budget * (risk_per_trade_pct / 100)
loss_per_share = price * abs(stop_loss_pct / 100)
if loss_per_share == 0:
return 0
shares = int(max_loss_amount / loss_per_share)
# 종목당 최대 비중 10% 제한
max_shares = int(budget * 0.10 / price)
return min(shares, max_shares)예시 계산:
예산: 1억 원, 주가: 50,000원, 손절:
손절 / 익절 전략
리스크 파라미터
RISK_PARAMS = {
"stop_loss_pct": -3.0, # 손절: -3%
"take_profit_pct": 6.0, # 익절: +6% (R:R = 1:2)
"trailing_stop_pct": -2.0, # 트레일링 스톱: 고점 대비 -2%
"max_holding_days": 20, # 최대 보유 기간: 20 영업일
"max_position_pct": 10.0, # 종목당 최대 비중: 10%
}| 항목 | 값 | 설명 |
|---|---|---|
| 손절 | -3% | 진입가 대비 3% 하락 시 강제 청산 |
| 익절 | +6% | 진입가 대비 6% 상승 시 수익 실현 |
| 트레일링 스톱 | -2% | 보유 중 최고가 대비 2% 하락 시 청산 |
| 최대 보유 | 20영업일 | 약 1개월 후 강제 청산 |
| 최대 비중 | 10% | 한 종목에 전체 자산의 10%까지만 투자 |
손절:익절 비율이 1:2라면 거래 비용 전 손익분기 승률은 약 33.3%입니다. 비용과 슬리피지를 넣으면 필요한 승률은 더 높아집니다. 표의 손절·익절 수치는 계산 예시이므로 실제 값은 백테스트와 위험 한도로 정해야 합니다.
트레일링 스톱
트레일링 스톱은 주가가 상승할 때 손절선도 함께 올라가는 방식입니다. 수익이 난 상태에서 급락 시 이익을 보전할 수 있습니다.
graph LR
A["진입: 50,000원"] --> B["최고가: 55,000원"]
B --> C["트레일링 스톱: 53,900원<br/>(55,000 * 0.98)"]
C --> D["현재가: 53,500원"]
D --> E["청산 (수익 +7%)"]
백테스트 고려사항
실전 적용 전 반드시 과거 데이터로 백테스트를 수행해야 합니다. 다음 사항을 반영하지 않으면 과도하게 낙관적인 결과가 나옵니다.
거래 비용
아래 값은 백테스트 코드에 비용 항목을 넣는 방법을 보이는 가정입니다. 실제 수수료와 세금은 증권사, 상품, 거래 시점에 맞춰 갱신해야 합니다.
| 항목 | 비율 |
|---|---|
| 매수 수수료 | 0.015% |
| 매도 수수료 | 0.015% |
| 매도 세금 예시 | 0.20% |
| 왕복 총 비용 예시 | 약 0.23% |
슬리피지 (호가 단위)
KRX 유가증권·코스닥 보통주의 호가 단위는 가격 범위에 따라 달라집니다. 아래 표는 KRX 업무규정 시행세칙의 주권 가격대별 호가 단위를 옮긴 것입니다.
| 주가 범위 | 호가 단위 |
|---|---|
| 2,000원 미만 | 1원 |
| 2,000원 이상 5,000원 미만 | 5원 |
| 5,000원 이상 20,000원 미만 | 10원 |
| 20,000원 이상 50,000원 미만 | 50원 |
| 50,000원 이상 200,000원 미만 | 100원 |
| 200,000원 이상 500,000원 미만 | 500원 |
| 500,000원 이상 | 1,000원 |
슬리피지는 예상가와 실제 체결가의 차이이므로 백테스트에서 반영해야 합니다. 세부 기준은 KRX 시장별 매매제도에서 확인할 수 있습니다.
주의사항
| 항목 | 설명 |
|---|---|
| Look-ahead bias | 지표 계산에 미래 데이터 사용 금지 (shift 확인) |
| 생존자 편향 | 상장 폐지 종목을 포함한 데이터로 백테스트 |
| 준비 구간 | 200일 이동평균이면 최소 200개 이전 관측치를 확보합니다. |
| 거래량 제약 | 주문 상한을 일평균 거래량의 일정 비율로 두고 민감도를 검증합니다. |
Look-ahead bias는 현재 봉의 종가로 계산한 지표를 같은 봉의 체결 판단에 쓰면 발생합니다. 다음 봉에서 거래하도록 신호를 최소
shift(1)만큼 늦춰야 합니다.
전략 요약
flowchart TD
DATA["OHLCV 데이터"] --> EMA["EMA 크로스오버"]
DATA --> RSI_C["RSI 계산"]
DATA --> MACD_C["MACD 계산"]
EMA --> DIR1["강세·약세·중립 투표"]
RSI_C --> DIR2["강세·약세·중립 투표"]
MACD_C --> DIR3["강세·약세·중립 투표"]
DIR1 --> SCORE["방향별 표 수 집계"]
DIR2 --> SCORE
DIR3 --> SCORE
SCORE --> BUY{"강세 표 >= 2?"}
SCORE --> SELL{"약세 표 >= 2?"}
BUY -->|예| POS["포지션 사이징 → 매수"]
SELL -->|예| EXIT["청산"]
BUY -->|아니오| HOLD["보유 유지"]
SELL -->|아니오| HOLD
POS --> RISK["리스크 관리"]
RISK --> SL["손절 -3%"]
RISK --> TP["익절 +6%"]
RISK --> TS["트레일링 스톱 -2%"]
RISK --> MH["최대 보유 20일"]
핵심 정리
- EMA 크로스오버로 추세 방향을 파악합니다
- RSI로 과매수/과매도 상태를 확인하고, 극단적 영역에서의 진입을 방지합니다
- MACD 히스토그램으로 추세 강도와 전환 시점을 판단합니다
- 2개 이상의 지표가 일치할 때만 진입하여 거짓 신호를 필터링합니다
- 한국 시장 특성에 맞게 코스피/코스닥별 파라미터를 차별 적용합니다
- 고정 비율 포지션 사이징으로 1회 거래 리스크를 1%로 제한합니다
- **손절(-3%), 익절(+6%), 트레일링 스톱(-2%)**으로 리스크를 관리합니다
정리
이 전략은 EMA, RSI, MACD가 같은 방향으로 두 표 이상 모일 때 신호를 냅니다. 방향별 표를 따로 세므로 두 강세 표와 한 약세 표도 정확히 매수로 판정합니다. RSI 극단 구간은 중립 처리해 과열 상태에서 새로 진입하지 않습니다.
제시한 시장별 기간과 위험 수치는 검증을 시작할 때 쓰는 값입니다. 실제 적용 전에는 최신 거래 비용과 호가 단위를 반영해야 합니다. look-ahead bias가 없는 워크포워드 백테스트로 적용할 값을 결정해야 합니다.